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