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