1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 package com.sun.media.sound; 26 27 import java.io.IOException; 28 import java.io.InputStream; 29 import javax.sound.sampled.AudioFormat; 30 import javax.sound.sampled.AudioInputStream; 31 import javax.sound.sampled.AudioSystem; 32 import javax.sound.sampled.AudioFormat.Encoding; 33 34 /** 35 * Wavetable oscillator for pre-loaded data. 36 * 37 * @author Karl Helgason 38 */ 39 public class ModelByteBufferWavetable implements ModelWavetable { 40 41 private class Buffer8PlusInputStream extends InputStream { 42 43 private boolean bigendian; 44 private int framesize_pc; 45 int pos = 0; 46 int pos2 = 0; 47 int markpos = 0; 48 int markpos2 = 0; 49 Buffer8PlusInputStream()50 public Buffer8PlusInputStream() { 51 framesize_pc = format.getFrameSize() / format.getChannels(); 52 bigendian = format.isBigEndian(); 53 } 54 read(byte[] b, int off, int len)55 public int read(byte[] b, int off, int len) throws IOException { 56 int avail = available(); 57 if (avail <= 0) 58 return -1; 59 if (len > avail) 60 len = avail; 61 byte[] buff1 = buffer.array(); 62 byte[] buff2 = buffer8.array(); 63 pos += buffer.arrayOffset(); 64 pos2 += buffer8.arrayOffset(); 65 if (bigendian) { 66 for (int i = 0; i < len; i += (framesize_pc + 1)) { 67 System.arraycopy(buff1, pos, b, i, framesize_pc); 68 System.arraycopy(buff2, pos2, b, i + framesize_pc, 1); 69 pos += framesize_pc; 70 pos2 += 1; 71 } 72 } else { 73 for (int i = 0; i < len; i += (framesize_pc + 1)) { 74 System.arraycopy(buff2, pos2, b, i, 1); 75 System.arraycopy(buff1, pos, b, i + 1, framesize_pc); 76 pos += framesize_pc; 77 pos2 += 1; 78 } 79 } 80 pos -= buffer.arrayOffset(); 81 pos2 -= buffer8.arrayOffset(); 82 return len; 83 } 84 skip(long n)85 public long skip(long n) throws IOException { 86 int avail = available(); 87 if (avail <= 0) 88 return -1; 89 if (n > avail) 90 n = avail; 91 pos += (n / (framesize_pc + 1)) * (framesize_pc); 92 pos2 += n / (framesize_pc + 1); 93 return super.skip(n); 94 } 95 read(byte[] b)96 public int read(byte[] b) throws IOException { 97 return read(b, 0, b.length); 98 } 99 read()100 public int read() throws IOException { 101 byte[] b = new byte[1]; 102 int ret = read(b, 0, 1); 103 if (ret == -1) 104 return -1; 105 return 0 & 0xFF; 106 } 107 markSupported()108 public boolean markSupported() { 109 return true; 110 } 111 available()112 public int available() throws IOException { 113 return (int)buffer.capacity() + (int)buffer8.capacity() - pos - pos2; 114 } 115 mark(int readlimit)116 public synchronized void mark(int readlimit) { 117 markpos = pos; 118 markpos2 = pos2; 119 } 120 reset()121 public synchronized void reset() throws IOException { 122 pos = markpos; 123 pos2 = markpos2; 124 125 } 126 } 127 128 private float loopStart = -1; 129 private float loopLength = -1; 130 private ModelByteBuffer buffer; 131 private ModelByteBuffer buffer8 = null; 132 private AudioFormat format = null; 133 private float pitchcorrection = 0; 134 private float attenuation = 0; 135 private int loopType = LOOP_TYPE_OFF; 136 ModelByteBufferWavetable(ModelByteBuffer buffer)137 public ModelByteBufferWavetable(ModelByteBuffer buffer) { 138 this.buffer = buffer; 139 } 140 ModelByteBufferWavetable(ModelByteBuffer buffer, float pitchcorrection)141 public ModelByteBufferWavetable(ModelByteBuffer buffer, 142 float pitchcorrection) { 143 this.buffer = buffer; 144 this.pitchcorrection = pitchcorrection; 145 } 146 ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format)147 public ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format) { 148 this.format = format; 149 this.buffer = buffer; 150 } 151 ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format, float pitchcorrection)152 public ModelByteBufferWavetable(ModelByteBuffer buffer, AudioFormat format, 153 float pitchcorrection) { 154 this.format = format; 155 this.buffer = buffer; 156 this.pitchcorrection = pitchcorrection; 157 } 158 set8BitExtensionBuffer(ModelByteBuffer buffer)159 public void set8BitExtensionBuffer(ModelByteBuffer buffer) { 160 buffer8 = buffer; 161 } 162 get8BitExtensionBuffer()163 public ModelByteBuffer get8BitExtensionBuffer() { 164 return buffer8; 165 } 166 getBuffer()167 public ModelByteBuffer getBuffer() { 168 return buffer; 169 } 170 getFormat()171 public AudioFormat getFormat() { 172 if (format == null) { 173 if (buffer == null) 174 return null; 175 InputStream is = buffer.getInputStream(); 176 AudioFormat format = null; 177 try { 178 format = AudioSystem.getAudioFileFormat(is).getFormat(); 179 } catch (Exception e) { 180 //e.printStackTrace(); 181 } 182 try { 183 is.close(); 184 } catch (IOException e) { 185 //e.printStackTrace(); 186 } 187 return format; 188 } 189 return format; 190 } 191 openStream()192 public AudioFloatInputStream openStream() { 193 if (buffer == null) 194 return null; 195 if (format == null) { 196 InputStream is = buffer.getInputStream(); 197 AudioInputStream ais = null; 198 try { 199 ais = AudioSystem.getAudioInputStream(is); 200 } catch (Exception e) { 201 //e.printStackTrace(); 202 return null; 203 } 204 return AudioFloatInputStream.getInputStream(ais); 205 } 206 if (buffer.array() == null) { 207 return AudioFloatInputStream.getInputStream(new AudioInputStream( 208 buffer.getInputStream(), format, buffer.capacity())); 209 } 210 if (buffer8 != null) { 211 if (format.getEncoding().equals(Encoding.PCM_SIGNED) 212 || format.getEncoding().equals(Encoding.PCM_UNSIGNED)) { 213 InputStream is = new Buffer8PlusInputStream(); 214 AudioFormat format2 = new AudioFormat( 215 format.getEncoding(), 216 format.getSampleRate(), 217 format.getSampleSizeInBits() + 8, 218 format.getChannels(), 219 format.getFrameSize() + (1 * format.getChannels()), 220 format.getFrameRate(), 221 format.isBigEndian()); 222 223 AudioInputStream ais = new AudioInputStream(is, format2, 224 buffer.capacity() / format.getFrameSize()); 225 return AudioFloatInputStream.getInputStream(ais); 226 } 227 } 228 return AudioFloatInputStream.getInputStream(format, buffer.array(), 229 (int)buffer.arrayOffset(), (int)buffer.capacity()); 230 } 231 getChannels()232 public int getChannels() { 233 return getFormat().getChannels(); 234 } 235 open(float samplerate)236 public ModelOscillatorStream open(float samplerate) { 237 // ModelWavetableOscillator doesn't support ModelOscillatorStream 238 return null; 239 } 240 241 // attenuation is in cB getAttenuation()242 public float getAttenuation() { 243 return attenuation; 244 } 245 // attenuation is in cB setAttenuation(float attenuation)246 public void setAttenuation(float attenuation) { 247 this.attenuation = attenuation; 248 } 249 getLoopLength()250 public float getLoopLength() { 251 return loopLength; 252 } 253 setLoopLength(float loopLength)254 public void setLoopLength(float loopLength) { 255 this.loopLength = loopLength; 256 } 257 getLoopStart()258 public float getLoopStart() { 259 return loopStart; 260 } 261 setLoopStart(float loopStart)262 public void setLoopStart(float loopStart) { 263 this.loopStart = loopStart; 264 } 265 setLoopType(int loopType)266 public void setLoopType(int loopType) { 267 this.loopType = loopType; 268 } 269 getLoopType()270 public int getLoopType() { 271 return loopType; 272 } 273 getPitchcorrection()274 public float getPitchcorrection() { 275 return pitchcorrection; 276 } 277 setPitchcorrection(float pitchcorrection)278 public void setPitchcorrection(float pitchcorrection) { 279 this.pitchcorrection = pitchcorrection; 280 } 281 } 282