/** * Class that represents a sound. This class is used by the students * to extend the capabilities of SimpleSound. * * Copyright Georgia Institute of Technology 2004 * @author Barbara Ericson ericson@cc.gatech.edu */ public class Sound extends SimpleSound { /////////////// consructors //////////////////////////////////// /** * Constructor that takes a file name * @param fileName the name of the file to read the sound from */ public Sound(String fileName) { // let the parent class handle setting the file name super(fileName); } /** * Constructor that takes the number of seconds that this * sound will have * @param numSeconds the number of seconds desired */ public Sound (int numSeconds) { // let the parent class handle this super(numSeconds); } /** * Constructor that takes a sound to copy */ public Sound (Sound copySound) { // let the parent class handle this super(copySound); } ////////////////// methods //////////////////////////////////// /** * Method to return the string representation of this sound * @return a string with information about this sound */ public String toString() { String output = "Sound"; String fileName = getFileName(); // if there is a file name then add that to the output if (fileName != null) output = output + " file: " + fileName; // add the length in frames output = output + " number of samples: " + getLengthInFrames(); return output; } // ----- Methods for Session 19 ------------------------------ /** * Computes the maximum difference between any two samples. * @return the maximum difference */ public int maximumDifferenceV1() { int maxSoFar = Math.abs( this.getSampleValueAt(0) - this.getSampleValueAt(1) ); int difference; for ( int i = 1; i < this.getLength()-1; i++ ) { difference = Math.abs( this.getSampleValueAt(i) - this.getSampleValueAt(i+1) ); if ( difference > maxSoFar ) { maxSoFar = difference; } } return maxSoFar; } /** * Computes the maximum difference between any two samples. * @return the **slot** that leads the maximum value change */ public int maximumDifference() { int answerSoFar = 0; int maxSoFar = Math.abs( this.getSampleValueAt(0) - this.getSampleValueAt(1) ); int difference; for ( int i = 1; i < this.getLength()-1; i++ ) { difference = Math.abs( this.getSampleValueAt(i) - this.getSampleValueAt(i+1) ); if ( difference > maxSoFar ) { answerSoFar = i; maxSoFar = difference; } } return answerSoFar; } /** * Computes an array of differences between adjacent samples. * @return an array of differences between adjacent samples. */ public int[] arrayOfDifferencesV1() { int[] differences = new int[ getLength()-1 ]; int difference; for ( int i = 0; i < this.getLength()-1; i++ ) { difference = this.getSampleValueAt(i) - this.getSampleValueAt(i+1); differences[i] = difference; } return differences; } public void displayDifferences( byte[] values, int start, int end ) { for (int i = start; i < end; i++ ) System.out.println( values[i] ); } public DiffSound compress() { int firstSample = this.getSampleValueAt(0); byte[] differences = arrayOfDifferences(); return new DiffSound( firstSample, differences ); } /** * Computes an array of differences between adjacent samples. * @return an array of differences between adjacent samples -- as bytes. */ private byte[] arrayOfDifferences() { byte[] differences = new byte[ getLength()-1 ]; byte difference; for ( int i = 0; i < this.getLength()-1; i++ ) { difference = (byte) (this.getSampleValueAt(i) - this.getSampleValueAt(i+1)); differences[i] = difference; } return differences; } // ----- Bonus methods for Session 19 ------------------------ public void subtract( Sound s ) { int value; for ( int i = 0; i < s.getLength(); i++ ) { value = this.getSampleValueAt( i ) - s.getSampleValueAt( i ); this.setSampleValueAt( i, value ); } } public static Sound createSineWave( int frequency, int amplitude ) { Sound result = new Sound( FileChooser.getMediaPath("sec3silence.wav") ); double samplingRate = result.getSamplingRate(); double rawValue = 0; int value = 0; double interval = 1.0 / frequency; double samplesPerCycle = interval * samplingRate; double maximumValue = 2 * Math.PI; for (int i = 0; i < result.getLength(); i++ ) { rawValue = Math.sin( (i/samplesPerCycle) * maximumValue ); value = (int) (amplitude * rawValue); result.setSampleValueAt( i, value ); } return result; } // ----- Methods for Session 18 ------------------------------ public static Sound makeBoxWave( int seconds ) { int length = seconds * 22050; // default sampling rate int amplitude = 10000; // default amplitude Sound result = new Sound( length ); int digit, upOrDown; for (int i = 0; i < length; i++ ) { digit = (i / 10) % 10; if ( digit < 5 ) // OR: digit % 2 == 0 upOrDown = 1; else upOrDown = -1; result.setSampleValueAt( i, upOrDown * amplitude ); } return result; } public void add( Sound s ) { int value; for ( int i = 0; i < this.getLength(); i++ ) { value = this.getSampleValueAt( i ) + s.getSampleValueAt( i ); this.setSampleValueAt( i, value ); } } public void blend( Sound sound1, Sound sound2 ) { int value1, value2; for ( int i = 0; i < 20000; i++ ) { value1 = sound1.getSampleValueAt( i ); this.setSampleValueAt( i, value1 ); } for ( int i = 0; i < 20000; i++ ) { value1 = sound1.getSampleValueAt( i ); value2 = sound2.getSampleValueAt( i ); this.setSampleValueAt( i+20000, value1/2 + value2/2 ); } for ( int i = 0; i < 20000; i++ ) { value2 = sound2.getSampleValueAt( i + 20000 ); this.setSampleValueAt( i+40000, value2 ); } } public static Sound blendedChord() { Sound c4note = new Sound( FileChooser.getMediaPath("bassoon-c4.wav") ); Sound e4note = new Sound( FileChooser.getMediaPath("bassoon-e4.wav") ); Sound g4note = new Sound( FileChooser.getMediaPath("bassoon-g4.wav") ); int value; int oneThird = c4note.getLength() / 3; Sound result = new Sound( 5 * oneThird ); for ( int i = 0; i < oneThird; i++ ) // 1/3 of c4 { value = c4note.getSampleValueAt( i ); result.setSampleValueAt( i, value ); } for ( int i = 0; i < oneThird; i++ ) // 1/3 of c4 + e4 { value = c4note.getSampleValueAt( i + oneThird ) + e4note.getSampleValueAt( i ); result.setSampleValueAt( i + oneThird, value ); } for ( int i = 0; i < oneThird; i++ ) // 1/3 of c4 + e4 + g4 { value = c4note.getSampleValueAt( i + 2*oneThird ) + e4note.getSampleValueAt( i + oneThird ) + g4note.getSampleValueAt( i ); result.setSampleValueAt( i + 2*oneThird, value ); } for ( int i = 0; i < oneThird; i++ ) // 1/3 of e4 + g4 { value = e4note.getSampleValueAt( i + 2*oneThird ) + g4note.getSampleValueAt( i + oneThird ); result.setSampleValueAt( i + 3*oneThird, value ); } for ( int i = 0; i < oneThird; i++ ) // 1/3 of g4 { value = g4note.getSampleValueAt( i + 2*oneThird ); result.setSampleValueAt( i + 4*oneThird, value ); } return result; } public void echo( int delay ) { Sound copy = new Sound( this.getFileName() ); int value; for ( int i = delay; i < this.getLength(); i++ ) { value = (int) (copy.getSampleValueAt( i-delay ) * 0.5); this.setSampleValueAt( i, value + this.getSampleValueAt(i) ); } } public void changeFrequency( double factor ) { Sound copy = new Sound( this.getFileName() ); for ( double iSource = 0, iTarget = 0; iTarget < this.getLength(); iSource += factor, iTarget++ ) { if ( iSource > copy.getLength() ) iSource = 0; this.setSampleValueAt( (int) iTarget, copy.getSampleValueAt( (int) iSource ) ); } } // ----- Methods for Session 17 ------------------------------ public Sound reverse() // different than textbook -- create new sound { int length = this.getLength(); Sound result = new Sound( this.getFileName() ); int value, slot; for ( int i = 0; i < length; i++ ) { value = this.getSampleValueAt( i ); slot = length - 1 - i; result.setSampleValueAt( slot, value ); } return result; } public Sound deepenTheVoice() { Sound source = new Sound( "/Users/wallingf/Desktop/the-voice-clipped-and-pitched.aiff" ); Sound target = new Sound( source.getLength() * 3/2 ); int firstSample, secondSample, average; for ( int i = 0, j = 0; i < source.getLength(); i+=2, j+=3 ) { firstSample = source.getSampleValueAt(i ); secondSample = source.getSampleValueAt(i+1); average = (firstSample + secondSample)/2; target.setSampleValueAt( j , firstSample ); target.setSampleValueAt( j+1, average ); target.setSampleValueAt( j+2, secondSample ); } return target; } // ----- Methods for Session 14 ------------------------------ public void displaySamples( int count ) { SoundSample[] samples = this.getSamples(); for (int i = 0; i < count; i++ ) System.out.println( samples[i] ); } public void amplify( double increase ) { for (int i = 0; i < this.getLength(); i++ ) { int value = this.getSampleValueAt( i ); this.setSampleValueAt( i, (int) (value * (1 + increase)) ); } } } // end of class Sound, put all new methods before this