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.demos.sandbox.audio;
034
035import java.awt.BorderLayout;
036import java.awt.Dimension;
037import java.awt.GridBagConstraints;
038import java.awt.GridBagLayout;
039import java.awt.HeadlessException;
040import java.util.ArrayList;
041import java.util.List;
042
043import javax.swing.JFrame;
044import javax.swing.JPanel;
045
046import org.jfree.chart.ChartFactory;
047import org.jfree.chart.ChartPanel;
048import org.jfree.chart.JFreeChart;
049import org.jfree.chart.plot.PlotOrientation;
050import org.jfree.data.xy.DefaultXYDataset;
051import org.openimaj.audio.AudioFormat;
052import org.openimaj.audio.SampleChunk;
053import org.openimaj.audio.conversion.SampleRateConverter;
054import org.openimaj.audio.conversion.SampleRateConverter.SampleRateConversionAlgorithm;
055import org.openimaj.audio.generation.Synthesizer;
056import org.openimaj.audio.samples.SampleBuffer;
057
058
059/**
060 *  @author David Dupplaw (dpd@ecs.soton.ac.uk)
061 *
062 *      @created 18 Jun 2012
063 */
064public class AudioSampleRateConversionTest
065{
066        /**
067         *  @param args
068         */
069        public static void main( final String[] args )
070    {
071                try
072        {
073                // ============================================================== //
074                // This is what we'll convert from
075                final AudioFormat inputFormat  = new AudioFormat( 16, 22.05, 1 );
076
077                // This is what we'll convert to
078                final AudioFormat outputFormat1 = new AudioFormat( 16, 11.025, 1 );
079                final AudioFormat outputFormat2 = new AudioFormat( 16, 44.1, 1 );
080
081                // Create a synthesiser to output stuff
082                final Synthesizer synth = new Synthesizer();
083                synth.setFrequency( 500 );
084                synth.setFormat( inputFormat );
085//              XuggleAudio xa = new XuggleAudio( new File( "videoplayback.3gp" ) );
086//              MultichannelToMonoProcessor synth = new MultichannelToMonoProcessor(xa);
087
088                // The sample rate converter we're testing
089                final SampleRateConverter src1 = new SampleRateConverter(
090                                SampleRateConversionAlgorithm.LINEAR_INTERPOLATION,
091                                outputFormat1 );
092                final SampleRateConverter src2 = new SampleRateConverter(
093                                SampleRateConversionAlgorithm.LINEAR_INTERPOLATION,
094                                outputFormat2 );
095
096                // ============================================================== //
097                // Add the synth's chunks to the display
098                final ArrayList<SampleChunk> chunks = new ArrayList<SampleChunk>();
099                for( int n = 0; n < 10; n++ )
100                        chunks.add( synth.nextSampleChunk().clone() );
101                final DefaultXYDataset ds1 = AudioSampleRateConversionTest.getDataSet( chunks );
102
103                for( int n = 0; n < chunks.size(); n++ )
104                        System.out.println( "Chunk "+n+" format: "+chunks.get(n).getFormat() );
105
106                // ============================================================== //
107                // Now add the resampled chunks to the display
108                final ArrayList<SampleChunk> resampledChunks1 = new ArrayList<SampleChunk>();
109                for( int n = 0; n < chunks.size(); n++ )
110                        resampledChunks1.add( src1.process( chunks.get(n) ).clone() );
111                final DefaultXYDataset ds2 = AudioSampleRateConversionTest.getDataSet( resampledChunks1 );
112                for( int n = 0; n < resampledChunks1.size(); n++ )
113                        System.out.println( "1: Resampled Chunk "+n+" format: "+resampledChunks1.get(n).getFormat() );
114                // ============================================================== //
115                final ArrayList<SampleChunk> resampledChunks2 = new ArrayList<SampleChunk>();
116                for( int n = 0; n < chunks.size(); n++ )
117                        resampledChunks2.add( src2.process( chunks.get(n) ).clone() );
118                final DefaultXYDataset ds3 = AudioSampleRateConversionTest.getDataSet( resampledChunks2 );
119                for( int n = 0; n < resampledChunks2.size(); n++ )
120                        System.out.println( "2: Resampled Chunk "+n+" format: "+resampledChunks2.get(n).getFormat() );
121
122                // ============================================================== //
123                // Set up the display
124                final JPanel p = new JPanel( new GridBagLayout() );
125                final GridBagConstraints gbc = new GridBagConstraints();
126                gbc.gridx = gbc.gridy = 0;
127                gbc.fill = GridBagConstraints.BOTH;
128                gbc.weightx = gbc.weighty = 1;
129
130                // ============================================================== //
131                // Add a chart of the original samples
132                JFreeChart c = ChartFactory.createXYLineChart( "Original Samples", "Amplitude",
133                        "Samples", ds1, PlotOrientation.HORIZONTAL, false, false,
134                        false );
135                ChartPanel chartPanel = new ChartPanel( c, false );
136                chartPanel.setPreferredSize( new Dimension( 1500, 300 ) );
137
138                gbc.gridy++;
139                p.add( chartPanel, gbc );
140
141                // ============================================================== //
142                // Add a chart of the resampled samples
143                c = ChartFactory.createXYLineChart( "Downsampled Samples", "Amplitude",
144                        "Samples", ds2, PlotOrientation.HORIZONTAL, false, false,
145                        false );
146                chartPanel = new ChartPanel( c, false );
147                chartPanel.setPreferredSize( new Dimension( 1500, 300 ) );
148
149                gbc.gridy++;
150                p.add( chartPanel, gbc );
151
152                // ============================================================== //
153                // Add a chart of the resampled samples
154                c = ChartFactory.createXYLineChart( "Upsampled Samples", "Amplitude",
155                        "Samples", ds3, PlotOrientation.HORIZONTAL, false, false,
156                        false );
157                chartPanel = new ChartPanel( c, false );
158                chartPanel.setPreferredSize( new Dimension( 1500, 300 ) );
159
160                gbc.gridy++;
161                p.add( chartPanel, gbc );
162
163                // ============================================================== //
164                // Display
165                final JFrame f = new JFrame();
166                f.add( p, BorderLayout.CENTER );
167                f.pack();
168                f.setVisible( true );
169        }
170        catch( final HeadlessException e )
171        {
172                e.printStackTrace();
173        }
174        catch( final Exception e )
175        {
176                e.printStackTrace();
177        }
178    }
179
180        /**
181         *      Returns a data set that displays the sample chunks.
182         *
183         *  @param chunks
184         *  @return a dataset
185         */
186        public static DefaultXYDataset getDataSet( final List<SampleChunk> chunks )
187        {
188                final DefaultXYDataset ds = new DefaultXYDataset();
189
190                int x = 0, y = 0;
191                for( int n = 0; n < chunks.size(); n++ )
192                {
193                        final SampleChunk sc = chunks.get(n);
194                        final SampleBuffer b = sc.getSampleBuffer();
195
196                        // Convert sample to a XY data plot
197                        final double[][] data = new double[2][];
198                        data[0] = new double[b.size()]; // x
199                        data[1] = new double[b.size()]; // y
200
201                        for( x = 0; x < b.size(); x++ )
202                        {
203                                data[0][x] = b.get(x);
204                                data[1][x] = x+y;
205                        }
206
207                        y += x;
208
209                        ds.addSeries( "samples "+n, data );
210                }
211
212                return ds;
213        }
214}