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.processor; 034 035import org.openimaj.audio.AudioStream; 036import org.openimaj.audio.SampleChunk; 037 038/** 039 * An interface for objects that are able to process audio sample data. Due to 040 * the fact that audio processors provide processed audio, they are also able to 041 * implement the {@link AudioStream} interface thereby making processors 042 * chainable. 043 * 044 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 045 * @created 8 Jun 2011 046 * 047 */ 048public abstract class AudioProcessor extends AudioStream 049{ 050 /** The audio stream to process in a chain */ 051 private AudioStream stream = null; 052 053 /** 054 * A default constructor for processing sample chunks or files in an ad-hoc 055 * manner. 056 */ 057 public AudioProcessor() 058 { 059 } 060 061 /** 062 * Construct a new processor based on the given stream. This processor can 063 * then be used as a stream itself in a chain. 064 * 065 * @param a 066 * The audio stream to process. 067 */ 068 public AudioProcessor(final AudioStream a) 069 { 070 this.stream = a; 071 if (a != null) 072 this.format = a.getFormat().clone(); 073 } 074 075 /** 076 * Function to process a whole audio stream. If the process returns null, it 077 * will stop the processing of the audio stream. Note that the output of the 078 * audio stream processing is not stored (it may be a live stream and so 079 * would be too large to store), so the caller must interact with the audio 080 * processor themselves to retrieve any useful information from the 081 * processing. 082 * 083 * @param a 084 * The audio stream to process. 085 * @throws Exception 086 * If the processing failed 087 */ 088 public void process(final AudioStream a) throws Exception 089 { 090 this.stream = a; 091 while (this.nextSampleChunk() != null) 092 ; 093 this.processingComplete(a); 094 } 095 096 /** 097 * Function that takes a sample chunk and processes the chunk. It should 098 * also return a sample chunk containing the processed data. If wished, the 099 * chunk may be side-affected and the input chunk returned. It should not be 100 * assumed that the input chunk will be side-affected, but it must be noted 101 * that it is possible that it could be. This process function may also 102 * return null. If null is returned it means that the rest of the audio 103 * stream is not required to be processed by this processing function. 104 * Whether the rest of the sample chunks are copied or ignored is up to the 105 * caller. 106 * 107 * @param sample 108 * The sample chunk to process. 109 * @return A sample chunk containing processed data. 110 * @throws Exception 111 * If the processing could not take place 112 */ 113 public abstract SampleChunk process(SampleChunk sample) throws Exception; 114 115 /** 116 * Called when the processing of a given audio stream has been completed. 117 * This can be used to alter the audio stream's properties. 118 * 119 * @param a 120 * The audio stream that has finished processing. 121 */ 122 public void processingComplete(final AudioStream a) 123 { 124 // Default is no implementation. Override this if necessary. 125 } 126 127 /** 128 * {@inheritDoc} 129 * 130 * @see org.openimaj.audio.AudioStream#nextSampleChunk() 131 */ 132 @Override 133 public SampleChunk nextSampleChunk() 134 { 135 try 136 { 137 final SampleChunk s = this.stream.nextSampleChunk(); 138 return (s != null ? this.process(s) : null); 139 } catch (final Exception e) 140 { 141 e.printStackTrace(); 142 return null; 143 } 144 } 145 146 /** 147 * Get the underlying stream. Will return null for non-chained audio 148 * processors. 149 * 150 * @return The underlying stream on chained processors. 151 */ 152 public AudioStream getUnderlyingStream() 153 { 154 return this.stream; 155 } 156 157 /** 158 * Sets the underlying stream, allowing it to be changed. 159 * 160 * @param stream 161 * The stream 162 */ 163 public void setUnderlyingStream(final AudioStream stream) 164 { 165 this.stream = stream; 166 if (stream != null) 167 this.format = stream.getFormat().clone(); 168 } 169 170 /** 171 * {@inheritDoc} 172 * 173 * The implementation in this class just calls reset on the wrapped stream 174 * (if it's set). 175 * 176 * @see org.openimaj.audio.AudioStream#reset() 177 */ 178 @Override 179 public void reset() 180 { 181 if (this.stream != null) { 182 stream.reset(); 183 } 184 } 185 186 /** 187 * {@inheritDoc} 188 * 189 * @see org.openimaj.audio.AudioStream#getLength() 190 */ 191 @Override 192 public long getLength() 193 { 194 return this.stream.getLength(); 195 } 196}