View Javadoc

1   /**
2    * Copyright (c) 2011, The University of Southampton and the individual contributors.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    *
8    *   * 	Redistributions of source code must retain the above copyright notice,
9    * 	this list of conditions and the following disclaimer.
10   *
11   *   *	Redistributions in binary form must reproduce the above copyright notice,
12   * 	this list of conditions and the following disclaimer in the documentation
13   * 	and/or other materials provided with the distribution.
14   *
15   *   *	Neither the name of the University of Southampton nor the names of its
16   * 	contributors may be used to endorse or promote products derived from this
17   * 	software without specific prior written permission.
18   *
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  /**
31   *
32   */
33  package org.openimaj.audio.analysis.benchmarking;
34  
35  import java.util.List;
36  import java.util.ListIterator;
37  
38  import org.openimaj.audio.AudioFormat;
39  import org.openimaj.audio.AudioStream;
40  import org.openimaj.audio.SampleChunk;
41  import org.openimaj.audio.samples.SampleBuffer;
42  import org.openimaj.data.dataset.ListDataset;
43  
44  /**
45   *	A class for helping to deal with datasets of audio information.
46   *
47   *	@author David Dupplaw (dpd@ecs.soton.ac.uk)
48   *  @created 14 May 2013
49   *	@version $Author$, $Revision$, $Date$
50   */
51  public class AudioDatasetHelper
52  {
53  	/**
54  	 * 	From a dataset that contains sample buffers, this method will return an
55  	 * 	{@link AudioStream} which will return each of the sample buffers in turn.
56  	 * 	The returned stream will have an undefined length (-1). If you need to know
57  	 * 	the length of the stream, use {@link #calculateStreamLength(ListDataset)}.
58  	 *
59  	 *	@param samples The samples
60  	 *	@return The audio stream
61  	 */
62  	static public AudioStream getAudioStream( final ListDataset<List<SampleBuffer>> samples )
63  	{
64  		final long streamLength = -1;
65  		return new AudioStream()
66  		{
67  			private int index = 0;
68  			private List<SampleBuffer> l = null;
69  			private int listIndex = 0;
70  			private long timecodeOffset = 0;
71  			private long currentTimecode = 0;
72  
73  			@Override
74  			public void reset()
75  			{
76  				this.listIndex = 0;
77  				this.l = null;
78  				this.index = 0;
79  				this.timecodeOffset = 0;
80  				this.currentTimecode = 0;
81  			}
82  
83  			@Override
84  			public SampleChunk nextSampleChunk()
85  			{
86  				if( this.listIndex >= samples.size() )
87  					return null;
88  
89  				if( this.l == null || this.index >= this.l.size() )
90  				{
91  					this.l = samples.get(this.listIndex);
92  					this.index = 0;
93  					this.listIndex++;
94  					this.timecodeOffset += this.currentTimecode;
95  				}
96  
97  				// Get the current sample chunk
98  				final SampleChunk sc = this.l.get(this.index).getSampleChunk();
99  
100 				// Work out the timecode at the end of the sample chunk
101 				this.currentTimecode = (long)(sc.getStartTimecode().getTimecodeInMilliseconds() +
102 						sc.getNumberOfSamples() / sc.getFormat().getSampleRateKHz());
103 
104 				// Add the offset into the current timecode.
105 				sc.getStartTimecode().setTimecodeInMilliseconds(
106 					sc.getStartTimecode().getTimecodeInMilliseconds() + this.timecodeOffset );
107 
108 				this.index++;
109 
110 				return sc;
111 			}
112 
113 			@Override
114 			public long getLength()
115 			{
116 				return streamLength;
117 			}
118 
119 			@Override
120 			public AudioFormat getFormat()
121 			{
122 				final SampleChunk sc = this.nextSampleChunk();
123 				this.reset();
124 				return sc.getFormat();
125 			}
126 		};
127 	}
128 
129 	/**
130 	 * 	Calculate the length of the stream of samples that will come from the dataset.
131 	 *
132 	 *	@param samples The sample list
133 	 *	@return The length of the stream in milliseconds
134 	 */
135 	public static long calculateStreamLength( final ListDataset<List<SampleBuffer>> samples )
136 	{
137 		final ListIterator<List<SampleBuffer>> i = samples.listIterator();
138 		long length = 0;
139 		while( i.hasNext() )
140 		{
141 			final List<SampleBuffer> l = i.next();
142 			for( final SampleBuffer sb : l )
143 			{
144 				length += sb.size() / sb.getFormat().getNumChannels() * sb.getFormat().getSampleRateKHz();
145 			}
146 		}
147 
148 		return length;
149 	}
150 }