0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "emu10k1_synth_local.h"
0013
0014
0015
0016 #define BLANK_LOOP_START 4
0017 #define BLANK_LOOP_END 8
0018 #define BLANK_LOOP_SIZE 12
0019 #define BLANK_HEAD_SIZE 32
0020
0021
0022
0023
0024 int
0025 snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
0026 struct snd_util_memhdr *hdr,
0027 const void __user *data, long count)
0028 {
0029 int offset;
0030 int truesize, size, blocksize;
0031 __maybe_unused int loopsize;
0032 int loopend, sampleend;
0033 unsigned int start_addr;
0034 struct snd_emu10k1 *emu;
0035
0036 emu = rec->hw;
0037 if (snd_BUG_ON(!sp || !hdr))
0038 return -EINVAL;
0039
0040 if (sp->v.size == 0) {
0041 dev_dbg(emu->card->dev,
0042 "emu: rom font for sample %d\n", sp->v.sample);
0043 return 0;
0044 }
0045
0046
0047 sp->v.end -= sp->v.start;
0048 sp->v.loopstart -= sp->v.start;
0049 sp->v.loopend -= sp->v.start;
0050 sp->v.start = 0;
0051
0052
0053 sampleend = sp->v.end;
0054 if (sampleend > sp->v.size)
0055 sampleend = sp->v.size;
0056 loopend = sp->v.loopend;
0057 if (loopend > sampleend)
0058 loopend = sampleend;
0059
0060
0061 if (sp->v.loopstart >= sp->v.loopend)
0062 swap(sp->v.loopstart, sp->v.loopend);
0063
0064
0065 truesize = sp->v.size + BLANK_HEAD_SIZE;
0066 loopsize = 0;
0067 #if 0
0068 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
0069 loopsize = sp->v.loopend - sp->v.loopstart;
0070 truesize += loopsize;
0071 #endif
0072 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
0073 truesize += BLANK_LOOP_SIZE;
0074
0075
0076 blocksize = truesize;
0077 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
0078 blocksize *= 2;
0079 sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
0080 if (sp->block == NULL) {
0081 dev_dbg(emu->card->dev,
0082 "synth malloc failed (size=%d)\n", blocksize);
0083
0084 return -ENOSPC;
0085 }
0086
0087 sp->v.truesize = blocksize;
0088
0089
0090 offset = 0;
0091 size = BLANK_HEAD_SIZE;
0092 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
0093 size *= 2;
0094 if (offset + size > blocksize)
0095 return -EINVAL;
0096 snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
0097 offset += size;
0098
0099
0100 size = loopend;
0101 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
0102 size *= 2;
0103 if (offset + size > blocksize)
0104 return -EINVAL;
0105 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
0106 snd_emu10k1_synth_free(emu, sp->block);
0107 sp->block = NULL;
0108 return -EFAULT;
0109 }
0110 offset += size;
0111 data += size;
0112
0113 #if 0
0114
0115 if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
0116
0117 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
0118 int woffset;
0119 unsigned short *wblock = (unsigned short*)block;
0120 woffset = offset / 2;
0121 if (offset + loopsize * 2 > blocksize)
0122 return -EINVAL;
0123 for (i = 0; i < loopsize; i++)
0124 wblock[woffset + i] = wblock[woffset - i -1];
0125 offset += loopsize * 2;
0126 } else {
0127 if (offset + loopsize > blocksize)
0128 return -EINVAL;
0129 for (i = 0; i < loopsize; i++)
0130 block[offset + i] = block[offset - i -1];
0131 offset += loopsize;
0132 }
0133
0134
0135 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
0136 sp->v.loopend += loopsize;
0137 } else {
0138 sp->v.loopstart += loopsize;
0139 sp->v.loopend += loopsize;
0140 }
0141
0142 sp->v.end += loopsize;
0143 }
0144 #endif
0145
0146
0147 size = sp->v.size - loopend;
0148 if (size < 0)
0149 return -EINVAL;
0150 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
0151 size *= 2;
0152 if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
0153 snd_emu10k1_synth_free(emu, sp->block);
0154 sp->block = NULL;
0155 return -EFAULT;
0156 }
0157 offset += size;
0158
0159
0160 if (offset < blocksize)
0161 snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
0162
0163 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
0164
0165 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
0166 sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
0167 sp->v.loopend = sp->v.end + BLANK_LOOP_END;
0168 }
0169 }
0170
0171 #if 0
0172 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
0173
0174 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
0175 unsigned short *wblock = (unsigned short*)block;
0176 for (i = 0; i < truesize; i++)
0177 wblock[i] ^= 0x8000;
0178 } else {
0179 for (i = 0; i < truesize; i++)
0180 block[i] ^= 0x80;
0181 }
0182 }
0183 #endif
0184
0185
0186 start_addr = BLANK_HEAD_SIZE * 2;
0187 if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
0188 start_addr >>= 1;
0189 sp->v.start += start_addr;
0190 sp->v.end += start_addr;
0191 sp->v.loopstart += start_addr;
0192 sp->v.loopend += start_addr;
0193
0194 return 0;
0195 }
0196
0197
0198
0199
0200 int
0201 snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
0202 struct snd_util_memhdr *hdr)
0203 {
0204 struct snd_emu10k1 *emu;
0205
0206 emu = rec->hw;
0207 if (snd_BUG_ON(!sp || !hdr))
0208 return -EINVAL;
0209
0210 if (sp->block) {
0211 snd_emu10k1_synth_free(emu, sp->block);
0212 sp->block = NULL;
0213 }
0214 return 0;
0215 }
0216