1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "emu10k1_synth_local.h"
26
27
28
29#define BLANK_LOOP_START 4
30#define BLANK_LOOP_END 8
31#define BLANK_LOOP_SIZE 12
32#define BLANK_HEAD_SIZE 32
33
34
35
36
37int
38snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
39 struct snd_util_memhdr *hdr,
40 const void __user *data, long count)
41{
42 int offset;
43 int truesize, size, loopsize, blocksize;
44 int loopend, sampleend;
45 unsigned int start_addr;
46 struct snd_emu10k1 *emu;
47
48 emu = rec->hw;
49 if (snd_BUG_ON(!sp || !hdr))
50 return -EINVAL;
51
52 if (sp->v.size == 0) {
53 dev_dbg(emu->card->dev,
54 "emu: rom font for sample %d\n", sp->v.sample);
55 return 0;
56 }
57
58
59 sp->v.end -= sp->v.start;
60 sp->v.loopstart -= sp->v.start;
61 sp->v.loopend -= sp->v.start;
62 sp->v.start = 0;
63
64
65 sampleend = sp->v.end;
66 if (sampleend > sp->v.size)
67 sampleend = sp->v.size;
68 loopend = sp->v.loopend;
69 if (loopend > sampleend)
70 loopend = sampleend;
71
72
73 if (sp->v.loopstart >= sp->v.loopend) {
74 int tmp = sp->v.loopstart;
75 sp->v.loopstart = sp->v.loopend;
76 sp->v.loopend = tmp;
77 }
78
79
80 truesize = sp->v.size + BLANK_HEAD_SIZE;
81 loopsize = 0;
82#if 0
83 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
84 loopsize = sp->v.loopend - sp->v.loopstart;
85 truesize += loopsize;
86#endif
87 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
88 truesize += BLANK_LOOP_SIZE;
89
90
91 blocksize = truesize;
92 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
93 blocksize *= 2;
94 sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
95 if (sp->block == NULL) {
96 dev_dbg(emu->card->dev,
97 "synth malloc failed (size=%d)\n", blocksize);
98
99 return -ENOSPC;
100 }
101
102 sp->v.truesize = blocksize;
103
104
105 offset = 0;
106 size = BLANK_HEAD_SIZE;
107 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
108 size *= 2;
109 if (offset + size > blocksize)
110 return -EINVAL;
111 snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
112 offset += size;
113
114
115 size = loopend;
116 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
117 size *= 2;
118 if (offset + size > blocksize)
119 return -EINVAL;
120 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
121 snd_emu10k1_synth_free(emu, sp->block);
122 sp->block = NULL;
123 return -EFAULT;
124 }
125 offset += size;
126 data += size;
127
128#if 0
129
130 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
131
132 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
133 int woffset;
134 unsigned short *wblock = (unsigned short*)block;
135 woffset = offset / 2;
136 if (offset + loopsize * 2 > blocksize)
137 return -EINVAL;
138 for (i = 0; i < loopsize; i++)
139 wblock[woffset + i] = wblock[woffset - i -1];
140 offset += loopsize * 2;
141 } else {
142 if (offset + loopsize > blocksize)
143 return -EINVAL;
144 for (i = 0; i < loopsize; i++)
145 block[offset + i] = block[offset - i -1];
146 offset += loopsize;
147 }
148
149
150 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
151 sp->v.loopend += loopsize;
152 } else {
153 sp->v.loopstart += loopsize;
154 sp->v.loopend += loopsize;
155 }
156
157 sp->v.end += loopsize;
158 }
159#endif
160
161
162 size = sp->v.size - loopend;
163 if (size < 0)
164 return -EINVAL;
165 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
166 size *= 2;
167 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
168 snd_emu10k1_synth_free(emu, sp->block);
169 sp->block = NULL;
170 return -EFAULT;
171 }
172 offset += size;
173
174
175 if (offset < blocksize)
176 snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
177
178 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
179
180 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
181 sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
182 sp->v.loopend = sp->v.end + BLANK_LOOP_END;
183 }
184 }
185
186#if 0
187 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
188
189 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
190 unsigned short *wblock = (unsigned short*)block;
191 for (i = 0; i < truesize; i++)
192 wblock[i] ^= 0x8000;
193 } else {
194 for (i = 0; i < truesize; i++)
195 block[i] ^= 0x80;
196 }
197 }
198#endif
199
200
201 start_addr = BLANK_HEAD_SIZE * 2;
202 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
203 start_addr >>= 1;
204 sp->v.start += start_addr;
205 sp->v.end += start_addr;
206 sp->v.loopstart += start_addr;
207 sp->v.loopend += start_addr;
208
209 return 0;
210}
211
212
213
214
215int
216snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
217 struct snd_util_memhdr *hdr)
218{
219 struct snd_emu10k1 *emu;
220
221 emu = rec->hw;
222 if (snd_BUG_ON(!sp || !hdr))
223 return -EINVAL;
224
225 if (sp->block) {
226 snd_emu10k1_synth_free(emu, sp->block);
227 sp->block = NULL;
228 }
229 return 0;
230}
231
232