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 */
030package org.openimaj.demos.acmmm11.presentation.slides;
031
032import java.awt.Component;
033import java.awt.image.BufferedImage;
034import java.io.IOException;
035import java.net.URL;
036
037import org.openimaj.audio.AudioFormat;
038import org.openimaj.audio.FrequencyAudioSource;
039import org.openimaj.audio.FrequencyAudioSource.Listener;
040import org.openimaj.audio.JavaSoundAudioGrabber;
041import org.openimaj.content.slideshow.PictureSlide;
042import org.openimaj.image.FImage;
043import org.openimaj.image.ImageUtilities;
044import org.openimaj.image.MBFImage;
045import org.openimaj.math.geometry.shape.Rectangle;
046import org.openimaj.util.pair.Pair;
047
048/**
049 * Slide showing a picture overlayed with a live spectrogram.
050 *
051 * @author David Dupplaw (dpd@ecs.soton.ac.uk)
052 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
053 *
054 */
055public class AudioOutroSlide extends PictureSlide implements Listener {
056
057        private final int sampleChunkSize = 512;
058        private FImage spectra;
059        private BufferedImage buf = null;
060        private JavaSoundAudioGrabber xa;
061        private FrequencyAudioSource source;
062
063
064        /**
065         * Default constructor
066         * @param picture
067         * @throws IOException
068         */
069        public AudioOutroSlide(final URL picture) throws IOException {
070                super(picture);
071        }
072
073        @Override
074        public Component getComponent(final int width, final int height) throws IOException{
075                final Component comp = super.getComponent(width, height);
076                this.xa = new JavaSoundAudioGrabber(new AudioFormat( 16, 96.1, 1 ));
077                this.xa.setMaxBufferSize( this.sampleChunkSize );
078                new Thread( this.xa ).start();
079                this.source = new FrequencyAudioSource(this.xa);
080                this.source.addFrequencyListener(this,new Pair<Integer>(30,3400));
081                this.spectra = null;
082                return comp;
083        }
084
085        @Override
086        public void close(){
087                super.close();
088                if(this.xa!=null){
089
090                        this.xa.stop();
091                        this.xa = null;
092                }
093        }
094
095        @Override
096        public void consumeFrequency(final float[] fftReal, final float[] fftImag,final int low,final int high) {
097
098                final int blockWidth = 10;
099                final int blockHeight = 5;
100
101                if( this.spectra == null || this.spectra.getHeight() != (high-low) * blockHeight )
102                {
103                        this.spectra = new FImage( this.mbfImage.getWidth(), (high-low)*blockHeight);
104                }
105
106                this.spectra.shiftLeftInplace(blockWidth);
107                // Draw the spectra
108                for( int i = low; i < high; i++ )
109                {
110                        final float re = fftReal[i];
111                        final float im = fftImag[i];
112                        float mag = (float)Math.log(Math.sqrt( re*re + im*im )+1)/5;
113                        if( mag > 1 ) mag = 1;
114                        this.spectra.drawShapeFilled(new Rectangle(this.spectra.getWidth()-blockWidth, this.spectra.getHeight()-(i * blockHeight), blockWidth,blockHeight), mag );
115                }
116
117                final MBFImage toDraw = this.mbfImage.clone();
118                toDraw.drawImage(new MBFImage(this.spectra,this.spectra,this.spectra), (this.mbfImage.getWidth() - this.spectra.width)/2, this.mbfImage.getHeight() - this.spectra.height);
119                this.ic.setImage(this.buf = ImageUtilities.createBufferedImageForDisplay( toDraw, this.buf ));
120        }
121
122
123
124}