5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package com.sun.media.sound;
26
27 import java.io.IOException;
28 import java.util.Arrays;
29
30 import javax.sound.midi.MidiChannel;
31 import javax.sound.midi.VoiceStatus;
32
33 /**
34 * Abstract resampler class.
35 *
36 * @author Karl Helgason
37 */
38 public abstract class SoftAbstractResampler implements SoftResampler {
39
40 private class ModelAbstractResamplerStream implements SoftResamplerStreamer {
41
42 AudioFloatInputStream stream;
43 boolean stream_eof = false;
44 int loopmode;
57 int streampos = 0;
58 int nrofchannels = 2;
59 boolean noteOff_flag = false;
60 float[][] ibuffer;
61 boolean ibuffer_order = true;
62 float[] sbuffer;
63 int pad;
64 int pad2;
65 float[] ix = new float[1];
66 int[] ox = new int[1];
67 float samplerateconv = 1;
68 float pitchcorrection = 0;
69
70 ModelAbstractResamplerStream() {
71 pad = getPadding();
72 pad2 = getPadding() * 2;
73 ibuffer = new float[2][sector_size + pad2];
74 ibuffer_order = true;
75 }
76
77 public void noteOn(MidiChannel channel, VoiceStatus voice,
78 int noteNumber, int velocity) {
79 }
80
81 public void noteOff(int velocity) {
82 noteOff_flag = true;
83 }
84
85 public void open(ModelWavetable osc, float outputsamplerate)
86 throws IOException {
87
88 eof = false;
89 nrofchannels = osc.getChannels();
90 if (ibuffer.length < nrofchannels) {
91 ibuffer = new float[nrofchannels][sector_size + pad2];
92 }
93
94 stream = osc.openStream();
95 streampos = 0;
96 stream_eof = false;
97 pitchcorrection = osc.getPitchcorrection();
98 samplerateconv
99 = stream.getFormat().getSampleRate() / outputsamplerate;
100 looplen = osc.getLoopLength();
101 loopstart = osc.getLoopStart();
102 sector_loopstart = (int) (loopstart / sector_size);
103 sector_loopstart = sector_loopstart - 1;
104
118
119 target_pitch = samplerateconv;
120 current_pitch[0] = samplerateconv;
121
122 ibuffer_order = true;
123 loopdirection = true;
124 noteOff_flag = false;
125
126 for (int i = 0; i < nrofchannels; i++)
127 Arrays.fill(ibuffer[i], sector_size, sector_size + pad2, 0);
128 ix[0] = pad;
129 eof = false;
130
131 ix[0] = sector_size + pad;
132 sector_pos = -1;
133 streampos = -sector_size;
134
135 nextBuffer();
136 }
137
138 public void setPitch(float pitch) {
139 /*
140 this.pitch = (float) Math.pow(2f,
141 (pitchcorrection + pitch) / 1200.0f)
142 * samplerateconv;
143 */
144 this.target_pitch = (float)Math.exp(
145 (pitchcorrection + pitch) * (Math.log(2.0) / 1200.0))
146 * samplerateconv;
147
148 if (!started)
149 current_pitch[0] = this.target_pitch;
150 }
151
152 public void nextBuffer() throws IOException {
153 if (ix[0] < pad) {
154 if (markset) {
155 // reset to target sector
156 stream.reset();
157 ix[0] += streampos - (sector_loopstart * sector_size);
237 ibuffer_order = true;
238
239 }
240
241 }
242
243 public void reverseBuffers() {
244 ibuffer_order = !ibuffer_order;
245 for (int c = 0; c < nrofchannels; c++) {
246 float[] cbuff = ibuffer[c];
247 int len = cbuff.length - 1;
248 int len2 = cbuff.length / 2;
249 for (int i = 0; i < len2; i++) {
250 float x = cbuff[i];
251 cbuff[i] = cbuff[len - i];
252 cbuff[len - i] = x;
253 }
254 }
255 }
256
257 public int read(float[][] buffer, int offset, int len)
258 throws IOException {
259
260 if (eof)
261 return -1;
262
263 if (noteOff_flag)
264 if ((loopmode & 2) != 0)
265 if (loopdirection)
266 loopmode = 0;
267
268
269 float pitchstep = (target_pitch - current_pitch[0]) / len;
270 float[] current_pitch = this.current_pitch;
271 started = true;
272
273 int[] ox = this.ox;
274 ox[0] = offset;
275 int ox_end = len + offset;
276
356 for (int i = 0; i < nrofchannels; i++) {
357 if (buffer[i] != null) {
358 ix[0] = bak_ix;
359 ox[0] = bak_ox;
360 current_pitch[0] = bak_pitch;
361 interpolate(ibuffer[i], ix, ixend, current_pitch,
362 pitchstep, buffer[i], ox, ox_end);
363 }
364 }
365
366 if (eof) {
367 current_pitch[0] = this.target_pitch;
368 return ox[0] - offset;
369 }
370 }
371
372 current_pitch[0] = this.target_pitch;
373 return len;
374 }
375
376 public void close() throws IOException {
377 stream.close();
378 }
379 }
380
381 public abstract int getPadding();
382
383 public abstract void interpolate(float[] in, float[] in_offset,
384 float in_end, float[] pitch, float pitchstep, float[] out,
385 int[] out_offset, int out_end);
386
387 public final SoftResamplerStreamer openStreamer() {
388 return new ModelAbstractResamplerStream();
389 }
390 }
|
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.media.sound;
27
28 import java.io.IOException;
29 import java.util.Arrays;
30
31 import javax.sound.midi.MidiChannel;
32 import javax.sound.midi.VoiceStatus;
33
34 /**
35 * Abstract resampler class.
36 *
37 * @author Karl Helgason
38 */
39 public abstract class SoftAbstractResampler implements SoftResampler {
40
41 private class ModelAbstractResamplerStream implements SoftResamplerStreamer {
42
43 AudioFloatInputStream stream;
44 boolean stream_eof = false;
45 int loopmode;
58 int streampos = 0;
59 int nrofchannels = 2;
60 boolean noteOff_flag = false;
61 float[][] ibuffer;
62 boolean ibuffer_order = true;
63 float[] sbuffer;
64 int pad;
65 int pad2;
66 float[] ix = new float[1];
67 int[] ox = new int[1];
68 float samplerateconv = 1;
69 float pitchcorrection = 0;
70
71 ModelAbstractResamplerStream() {
72 pad = getPadding();
73 pad2 = getPadding() * 2;
74 ibuffer = new float[2][sector_size + pad2];
75 ibuffer_order = true;
76 }
77
78 @Override
79 public void noteOn(MidiChannel channel, VoiceStatus voice,
80 int noteNumber, int velocity) {
81 }
82
83 @Override
84 public void noteOff(int velocity) {
85 noteOff_flag = true;
86 }
87
88 @Override
89 public void open(ModelWavetable osc, float outputsamplerate)
90 throws IOException {
91
92 eof = false;
93 nrofchannels = osc.getChannels();
94 if (ibuffer.length < nrofchannels) {
95 ibuffer = new float[nrofchannels][sector_size + pad2];
96 }
97
98 stream = osc.openStream();
99 streampos = 0;
100 stream_eof = false;
101 pitchcorrection = osc.getPitchcorrection();
102 samplerateconv
103 = stream.getFormat().getSampleRate() / outputsamplerate;
104 looplen = osc.getLoopLength();
105 loopstart = osc.getLoopStart();
106 sector_loopstart = (int) (loopstart / sector_size);
107 sector_loopstart = sector_loopstart - 1;
108
122
123 target_pitch = samplerateconv;
124 current_pitch[0] = samplerateconv;
125
126 ibuffer_order = true;
127 loopdirection = true;
128 noteOff_flag = false;
129
130 for (int i = 0; i < nrofchannels; i++)
131 Arrays.fill(ibuffer[i], sector_size, sector_size + pad2, 0);
132 ix[0] = pad;
133 eof = false;
134
135 ix[0] = sector_size + pad;
136 sector_pos = -1;
137 streampos = -sector_size;
138
139 nextBuffer();
140 }
141
142 @Override
143 public void setPitch(float pitch) {
144 /*
145 this.pitch = (float) Math.pow(2f,
146 (pitchcorrection + pitch) / 1200.0f)
147 * samplerateconv;
148 */
149 this.target_pitch = (float)Math.exp(
150 (pitchcorrection + pitch) * (Math.log(2.0) / 1200.0))
151 * samplerateconv;
152
153 if (!started)
154 current_pitch[0] = this.target_pitch;
155 }
156
157 public void nextBuffer() throws IOException {
158 if (ix[0] < pad) {
159 if (markset) {
160 // reset to target sector
161 stream.reset();
162 ix[0] += streampos - (sector_loopstart * sector_size);
242 ibuffer_order = true;
243
244 }
245
246 }
247
248 public void reverseBuffers() {
249 ibuffer_order = !ibuffer_order;
250 for (int c = 0; c < nrofchannels; c++) {
251 float[] cbuff = ibuffer[c];
252 int len = cbuff.length - 1;
253 int len2 = cbuff.length / 2;
254 for (int i = 0; i < len2; i++) {
255 float x = cbuff[i];
256 cbuff[i] = cbuff[len - i];
257 cbuff[len - i] = x;
258 }
259 }
260 }
261
262 @Override
263 public int read(float[][] buffer, int offset, int len)
264 throws IOException {
265
266 if (eof)
267 return -1;
268
269 if (noteOff_flag)
270 if ((loopmode & 2) != 0)
271 if (loopdirection)
272 loopmode = 0;
273
274
275 float pitchstep = (target_pitch - current_pitch[0]) / len;
276 float[] current_pitch = this.current_pitch;
277 started = true;
278
279 int[] ox = this.ox;
280 ox[0] = offset;
281 int ox_end = len + offset;
282
362 for (int i = 0; i < nrofchannels; i++) {
363 if (buffer[i] != null) {
364 ix[0] = bak_ix;
365 ox[0] = bak_ox;
366 current_pitch[0] = bak_pitch;
367 interpolate(ibuffer[i], ix, ixend, current_pitch,
368 pitchstep, buffer[i], ox, ox_end);
369 }
370 }
371
372 if (eof) {
373 current_pitch[0] = this.target_pitch;
374 return ox[0] - offset;
375 }
376 }
377
378 current_pitch[0] = this.target_pitch;
379 return len;
380 }
381
382 @Override
383 public void close() throws IOException {
384 stream.close();
385 }
386 }
387
388 public abstract int getPadding();
389
390 public abstract void interpolate(float[] in, float[] in_offset,
391 float in_end, float[] pitch, float pitchstep, float[] out,
392 int[] out_offset, int out_end);
393
394 @Override
395 public final SoftResamplerStreamer openStreamer() {
396 return new ModelAbstractResamplerStream();
397 }
398 }
|