001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030/** 031 * 032 */ 033package org.openimaj.audio.samples; 034 035import java.util.Iterator; 036 037import org.openimaj.audio.AudioFormat; 038import org.openimaj.audio.SampleChunk; 039import org.openimaj.audio.timecode.AudioTimecode; 040import org.openimaj.util.array.ArrayUtils; 041 042import gnu.trove.iterator.TFloatIterator; 043import gnu.trove.list.array.TFloatArrayList; 044 045/** 046 * An implementation of a sample buffer that maintains the floating point 047 * precision values. Note that this buffer has no timecode associated with it 048 * and that {@link SampleChunk}s cannot be retrieved from it. 049 * 050 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 051 * @created 27 Jul 2012 052 * @version $Author$, $Revision$, $Date$ 053 */ 054public class FloatSampleBuffer implements SampleBuffer, Iterator<Float> { 055 /** The samples */ 056 private float[] samples = null; 057 058 /** The audio format */ 059 private AudioFormat format = null; 060 061 /** Iterator over the samples in this buffer */ 062 private TFloatIterator tfIterator; 063 064 /** 065 * @param samples 066 * The samples to use 067 * @param af 068 * The audio format of the samples 069 */ 070 public FloatSampleBuffer(final float[] samples, final AudioFormat af) { 071 this.format = af.clone(); 072 this.format.setNBits(-1); 073 this.samples = samples; 074 } 075 076 /** 077 * 078 * @param samples 079 * The samples to use 080 * @param af 081 * The audio format 082 */ 083 public FloatSampleBuffer(final double[] samples, final AudioFormat af) { 084 this(ArrayUtils.convertToFloat(samples), af); 085 } 086 087 /** 088 * {@inheritDoc} 089 * 090 * @see org.openimaj.audio.samples.SampleBuffer#get(int) 091 */ 092 @Override 093 public float get(final int index) { 094 return this.samples[index]; 095 } 096 097 /** 098 * {@inheritDoc} 099 * 100 * @see org.openimaj.audio.samples.SampleBuffer#set(int, float) 101 */ 102 @Override 103 public void set(final int index, final float sample) { 104 this.samples[index] = sample; 105 } 106 107 /** 108 * {@inheritDoc} 109 * 110 * @see org.openimaj.audio.samples.SampleBuffer#size() 111 */ 112 @Override 113 public int size() { 114 return this.samples.length; 115 } 116 117 /** 118 * {@inheritDoc} 119 * 120 * @see org.openimaj.audio.samples.SampleBuffer#getFormat() 121 */ 122 @Override 123 public AudioFormat getFormat() { 124 return this.format; 125 } 126 127 /** 128 * {@inheritDoc} 129 * 130 * @see org.openimaj.audio.samples.SampleBuffer#setFormat(org.openimaj.audio.AudioFormat) 131 */ 132 @Override 133 public void setFormat(final AudioFormat af) { 134 this.format = af.clone(); 135 this.format.setNBits(-1); 136 } 137 138 /** 139 * Returns NULL. If you need a sample chunk from this sample buffer, then 140 * you must instantiate the appropriate sample chunk first and fill it. It 141 * cannot be done from this class because this class no longer knows how 142 * many bits you would like the sample chunk to be created as. 143 * 144 * {@inheritDoc} 145 * 146 * @see org.openimaj.audio.samples.SampleBuffer#getSampleChunk() 147 */ 148 @Override 149 public SampleChunk getSampleChunk() { 150 return null; 151 } 152 153 /** 154 * Returns NULL. If you need a sample chunk from this sample buffer, then 155 * you must instantiate the appropriate sample chunk first and fill it. It 156 * cannot be done from this class because this class no longer knows how 157 * many bits you would like the sample chunk to be created as. 158 * 159 * {@inheritDoc} 160 * 161 * @see org.openimaj.audio.samples.SampleBuffer#getSampleChunk(int) 162 */ 163 @Override 164 public SampleChunk getSampleChunk(final int channel) { 165 return null; 166 } 167 168 /** 169 * {@inheritDoc} 170 * 171 * @see org.openimaj.audio.samples.SampleBuffer#asDoubleArray() 172 */ 173 @Override 174 public double[] asDoubleArray() { 175 return ArrayUtils.convertToDouble(this.samples); 176 } 177 178 /** 179 * {@inheritDoc} 180 * 181 * @see org.openimaj.audio.samples.SampleBuffer#asDoubleChannelArray() 182 */ 183 @Override 184 public double[][] asDoubleChannelArray() { 185 final int nc = this.format.getNumChannels(); 186 final double[][] s = new double[nc][this.samples.length / nc]; 187 for (int c = 0; c < nc; c++) 188 for (int sa = 0; sa < this.samples.length / nc; sa++) 189 s[c][sa] = this.samples[sa * nc + c]; 190 return s; 191 } 192 193 /** 194 * {@inheritDoc} 195 * 196 * @see org.openimaj.audio.samples.SampleBuffer#asDoubleArray() 197 */ 198 @Override 199 public float[] asFloatArray() { 200 return this.samples; 201 } 202 203 /** 204 * {@inheritDoc} 205 * 206 * @see org.openimaj.audio.samples.SampleBuffer#asDoubleChannelArray() 207 */ 208 @Override 209 public float[][] asFloatChannelArray() { 210 final int nc = this.format.getNumChannels(); 211 final float[][] s = new float[nc][this.samples.length / nc]; 212 for (int c = 0; c < nc; c++) 213 for (int sa = 0; sa < this.samples.length / nc; sa++) 214 s[c][sa] = this.samples[sa * nc + c]; 215 return s; 216 } 217 218 /** 219 * {@inheritDoc} 220 * 221 * @see org.openimaj.audio.samples.SampleBuffer#getUnscaled(int) 222 */ 223 @Override 224 public float getUnscaled(final int index) { 225 return this.get(index); 226 } 227 228 /** 229 * Multipy the samples by the given scalar 230 * 231 * @param scalar 232 * The scalar 233 * @return this object 234 */ 235 public FloatSampleBuffer multiply(final double scalar) { 236 for (int i = 0; i < this.samples.length; i++) 237 this.set(i, (float) (this.samples[i] * scalar)); 238 return this; 239 } 240 241 /** 242 * Add the scalar to all the samples 243 * 244 * @param scalar 245 * The scalar 246 * @return this object 247 */ 248 public FloatSampleBuffer add(final double scalar) { 249 for (int i = 0; i < this.samples.length; i++) 250 this.set(i, (float) (this.samples[i] + scalar)); 251 return this; 252 } 253 254 /** 255 * {@inheritDoc} 256 * 257 * @see java.lang.Iterable#iterator() 258 */ 259 @Override 260 public Iterator<Float> iterator() { 261 this.tfIterator = this.tf_iterator(); 262 return this; 263 } 264 265 /** 266 * Returns a trove float iterator 267 * 268 * @return a trove float iterator 269 */ 270 public TFloatIterator tf_iterator() { 271 final TFloatArrayList l = new TFloatArrayList(); 272 for (final float f : this.samples) 273 l.add(f); 274 return l.iterator(); 275 } 276 277 /** 278 * {@inheritDoc} 279 * 280 * @see java.util.Iterator#hasNext() 281 */ 282 @Override 283 public boolean hasNext() { 284 return this.tfIterator.hasNext(); 285 } 286 287 /** 288 * {@inheritDoc} 289 * 290 * @see java.util.Iterator#next() 291 */ 292 @Override 293 public Float next() { 294 return this.tfIterator.next(); 295 } 296 297 /** 298 * {@inheritDoc} 299 * 300 * @see java.util.Iterator#remove() 301 */ 302 @Override 303 public void remove() { 304 this.tfIterator.remove(); 305 } 306 307 /** 308 * {@inheritDoc} 309 * 310 * @see org.openimaj.audio.samples.SampleBuffer#getStartTimecode() 311 */ 312 @Override 313 public AudioTimecode getStartTimecode() { 314 return null; 315 } 316}