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 snd_printd("emu: rom font for sample %d\n", sp->v.sample);
54 return 0;
55 }
56
57
58 sp->v.end -= sp->v.start;
59 sp->v.loopstart -= sp->v.start;
60 sp->v.loopend -= sp->v.start;
61 sp->v.start = 0;
62
63
64 sampleend = sp->v.end;
65 if (sampleend > sp->v.size)
66 sampleend = sp->v.size;
67 loopend = sp->v.loopend;
68 if (loopend > sampleend)
69 loopend = sampleend;
70
71
72 if (sp->v.loopstart >= sp->v.loopend) {
73 int tmp = sp->v.loopstart;
74 sp->v.loopstart = sp->v.loopend;
75 sp->v.loopend = tmp;
76 }
77
78
79 truesize = sp->v.size + BLANK_HEAD_SIZE;
80 loopsize = 0;
81#if 0
82 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
83 loopsize = sp->v.loopend - sp->v.loopstart;
84 truesize += loopsize;
85#endif
86 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
87 truesize += BLANK_LOOP_SIZE;
88
89
90 blocksize = truesize;
91 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
92 blocksize *= 2;
93 sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
94 if (sp->block == NULL) {
95 snd_printd("emu10k1: synth malloc failed (size=%d)\n", blocksize);
96
97 return -ENOSPC;
98 }
99
100 sp->v.truesize = blocksize;
101
102
103 offset = 0;
104 size = BLANK_HEAD_SIZE;
105 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
106 size *= 2;
107 if (offset + size > blocksize)
108 return -EINVAL;
109 snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
110 offset += size;
111
112
113 size = loopend;
114 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
115 size *= 2;
116 if (offset + size > blocksize)
117 return -EINVAL;
118 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
119 snd_emu10k1_synth_free(emu, sp->block);
120 sp->block = NULL;
121 return -EFAULT;
122 }
123 offset += size;
124 data += size;
125
126#if 0
127
128 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
129
130 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
131 int woffset;
132 unsigned short *wblock = (unsigned short*)block;
133 woffset = offset / 2;
134 if (offset + loopsize * 2 > blocksize)
135 return -EINVAL;
136 for (i = 0; i < loopsize; i++)
137 wblock[woffset + i] = wblock[woffset - i -1];
138 offset += loopsize * 2;
139 } else {
140 if (offset + loopsize > blocksize)
141 return -EINVAL;
142 for (i = 0; i < loopsize; i++)
143 block[offset + i] = block[offset - i -1];
144 offset += loopsize;
145 }
146
147
148 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
149 sp->v.loopend += loopsize;
150 } else {
151 sp->v.loopstart += loopsize;
152 sp->v.loopend += loopsize;
153 }
154
155 sp->v.end += loopsize;
156 }
157#endif
158
159
160 size = sp->v.size - loopend;
161 if (size < 0)
162 return -EINVAL;
163 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
164 size *= 2;
165 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
166 snd_emu10k1_synth_free(emu, sp->block);
167 sp->block = NULL;
168 return -EFAULT;
169 }
170 offset += size;
171
172
173 if (offset < blocksize)
174 snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
175
176 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
177
178 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
179 sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
180 sp->v.loopend = sp->v.end + BLANK_LOOP_END;
181 }
182 }
183
184#if 0
185 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
186
187 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
188 unsigned short *wblock = (unsigned short*)block;
189 for (i = 0; i < truesize; i++)
190 wblock[i] ^= 0x8000;
191 } else {
192 for (i = 0; i < truesize; i++)
193 block[i] ^= 0x80;
194 }
195 }
196#endif
197
198
199 start_addr = BLANK_HEAD_SIZE * 2;
200 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
201 start_addr >>= 1;
202 sp->v.start += start_addr;
203 sp->v.end += start_addr;
204 sp->v.loopstart += start_addr;
205 sp->v.loopend += start_addr;
206
207 return 0;
208}
209
210
211
212
213int
214snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
215 struct snd_util_memhdr *hdr)
216{
217 struct snd_emu10k1 *emu;
218
219 emu = rec->hw;
220 if (snd_BUG_ON(!sp || !hdr))
221 return -EINVAL;
222
223 if (sp->block) {
224 snd_emu10k1_synth_free(emu, sp->block);
225 sp->block = NULL;
226 }
227 return 0;
228}
229
230