Difference between revisions of "CSC111 JES Page on Sound Processing"

From dftwiki3
Jump to: navigation, search
(Videos)
 
(13 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
--[[User:Thiebaut|D. Thiebaut]] ([[User talk:Thiebaut|talk]]) 20:12, 23 February 2014 (EST)
 
--[[User:Thiebaut|D. Thiebaut]] ([[User talk:Thiebaut|talk]]) 20:12, 23 February 2014 (EST)
 
----
 
----
 +
 +
<br />
 +
<center>[[File:SoundWave.jpg]]</center>
 +
<br />
 +
=Download Page=
 +
<br />
 +
* [https://code.google.com/p/mediacomp-jes/downloads/list code.google.com/mediacomp-jes/]
 +
<br />
 +
 +
<br />
 +
=Videos=
 +
<br />
 +
* <center><videoflash>s9GBf8y0lY0</videoflash>
 +
</center>
 +
<br />Physics of sound: A metal plate is connected to an oscillator and frequency is increased...
 +
* <center><videoflash>cK2-6cgqgYA</videoflash></center>
 +
<br />The source of waves] (1933).  You may skip after the first 6 minutes.
 +
* ''Morning Edition'' 's Report on [http://www.npr.org/templates/story/story.php?storyId=102234687 Guito Monks]
 +
 +
 +
[[Image:SoundMediaTool.png | right | 300px ]]
 +
* Sound Tool
 +
* Increasing the amplitude of the signal (doubling)
 +
* Noise issue
 +
* Decreasing the amplitude of the signal.
 +
* Reducing the noise
 +
* Saturating/clipping the noise
 +
* Copying sound clip
 +
* Creating an echo
 +
<br />
  
 
=Reference=
 
=Reference=
 +
<br />
 
* [http://www.csc.depauw.edu/~bhoward/courses/0304Winter/ref/  JES's reference page from Depauw University]
 
* [http://www.csc.depauw.edu/~bhoward/courses/0304Winter/ref/  JES's reference page from Depauw University]
 +
* [http://cs.smith.edu/classwiki/index.php/CSC111_Lab_7 Lab 7 CSC111 2010]
 +
* [http://cs.smith.edu/dftwiki/index.php/CSC231_Lab_6_2010 Lab 6 CSC231 2010]
 +
* [http://cs.smith.edu/classwiki/index.php/CSC111_Lab_7
  
 
=Installation=
 
=Installation=
 +
<br />
 +
==Sound Files==
 +
<br />
 +
* Get some sample wav files:
 +
 +
* [[media:hello.wav |hello.wav]]
 +
* [[media:goodbye.wav|goodbye.wav]]
 +
* [[media:dratcomp.wav|dratcomp.wav]]
 +
* [[media:force.wav|force.wav]]
 +
* [[media:takeover.wav|takeover.wav]]
 +
* [[Media:guitar.wav | guitar.wav]]
 +
 +
* ''Note'': There's more at http://buggerluggs.tripod.com/ie/wav-dir184.htm and http://www.duke.edu/~rfb/palace/wavs/dratcomp.wav.  If you want to download more to your account, simply find the URL of a wav file, for example http://www.duke.edu/~rfb/palace/wavs/energize.wav, and download it to your computer.
 +
<br />
 +
 
==If you want to install JES on your personal Windows computer==
 
==If you want to install JES on your personal Windows computer==
 +
<br />
 
If you want to install JES on your Windows laptop or computer, you can get Jes from the [http://code.google.com/p/mediacomp-jes/downloads/list Google code] web site.  Grab the 3.2.1 version for Windows and install it on your Windows machine.
 
If you want to install JES on your Windows laptop or computer, you can get Jes from the [http://code.google.com/p/mediacomp-jes/downloads/list Google code] web site.  Grab the 3.2.1 version for Windows and install it on your Windows machine.
 
+
<br />
 
==If you want to install JES on your personal Mac==
 
==If you want to install JES on your personal Mac==
 +
<br />
 
Jes for the Mac is available on [http://code.google.com/p/mediacomp-jes/downloads/list Google code].  Get Jes 3.2.1 for the Mac, open the zip file, and move the '''JES 3.2.1.app''' to your '''Applications''' folder.
 
Jes for the Mac is available on [http://code.google.com/p/mediacomp-jes/downloads/list Google code].  Get Jes 3.2.1 for the Mac, open the zip file, and move the '''JES 3.2.1.app''' to your '''Applications''' folder.
  
Line 15: Line 66:
  
 
* In the JES program area, type in the following main() function:
 
* In the JES program area, type in the following main() function:
 
+
<br />
 
<source lang="python">
 
<source lang="python">
  
Line 24: Line 75:
  
 
</source>
 
</source>
 
+
<br />
 
* Save the file as '''sound1.py'''
 
* Save the file as '''sound1.py'''
 
* Click on '''Load Program'''
 
* Click on '''Load Program'''
Line 32: Line 83:
 
* Make sure the speakers are on, but not too loud and listen to the sentence being played.   
 
* Make sure the speakers are on, but not too loud and listen to the sentence being played.   
 
* Try one or two other sound files.
 
* Try one or two other sound files.
 +
<br />
 +
<br />
 +
=Part 3: Altering a sound file=
 +
<br />
 +
* You will reduce the intensity of the sound by dividing all the samples by half
 +
* Copy/Paste the program below in JES
 +
* Read it to make sure you understand it.
 +
<br />
 +
<source lang="python">
 +
 +
 +
  # select  a sound file
 +
  file = pickAFile()
 +
  sound = makeSound( file )
 +
 +
  # play it
 +
  blockingPlay( sound )
 +
 +
  # lower its intensity by half
 +
  for i in range( 1, getLength( sound ) ):
 +
    value = getSampleValueAt( sound, i )    # get the value of the i-th sample
 +
    setSampleValueAt( sound, i, value / 2 )  # set the sample to half its original value
 +
 +
  # play new waveform back
 +
  blockingPlay( sound )
 +
 +
 +
</source>
 +
<br />
 +
=Part 4: Reversing a Sound File=
 +
 +
<center>[[Image:CSC111_lab3_sound1_sound2.png | 300px]]</center>
 +
 +
* The goal is to create 2 sound objects, '''sound1''' and '''sound2''' from the same file, and take the value of the sample at Index 1  in sound1 and to store it at Index N-1 in sound2.  Identically for the sample at Index 2 which will go to Index N-2 in sound2.
 +
 +
* Complete the table below and write down the relationship existing between i and j:
 +
 +
<br />
 +
<br />
 +
<br />
 +
 +
<center>
 +
{| border="1"
 +
| &nbsp;&nbsp;i&nbsp;&nbsp;
 +
| &nbsp;&nbsp;j&nbsp;&nbsp;
 +
| &nbsp;&nbsp;i+j&nbsp;&nbsp;
 +
|-
 +
| &nbsp;1
 +
| &nbsp;
 +
| &nbsp;
 +
|-
 +
| &nbsp;2
 +
| &nbsp;
 +
| &nbsp;
 +
|-
 +
| &nbsp;3
 +
| &nbsp;
 +
| &nbsp;
 +
|-
 +
| ...
 +
| &nbsp;
 +
| &nbsp;
 +
|-
 +
| N-2
 +
| &nbsp;
 +
| &nbsp;
 +
|-
 +
| N-1
 +
| &nbsp;
 +
| &nbsp;
 +
|}
 +
</center>
 +
<br />
 +
<br />
 +
<br />
 +
 +
* From the table above extract the equation that yields ''j'' as a function of ''i''
 +
* Write your for-loop to reverse sound1 into sound2
 +
 +
      N = ...
 +
      for i in range( 1, N ):
 +
            j = ...
 +
            sample = getSampleValueAt( sound1, i )
 +
            setSampleValueAt( sound2, j, sample )
 +
 +
* Test your program by making it play sound1 first, then sound2.
 +
 +
=Part 9: ECHO Echo echo=
 +
 +
Same as Part 8, but now you will make 2 copies of your sound object, attenuate the first one by 0.5, the second one by 0.25, and delay each by 5000 from each other, and create a reverberation effect.
 +
 +
<br />
 +
<br />
 +
 +
<center>[[Image:CSC111_Full_Echo.png | 300px]]</center>
 +
 +
<br />
 +
<br />
 +
=Sample Functions=
 +
<br />
 +
<source lang="python">
 +
# sound1.py
 +
# D. Thiebaut
 +
# 3/23/09
 +
# A collection of programs to treat and alter sound files
 +
 +
def doubleAmplitude( sound ):
 +
  # increases the value of each sample by doubling it
 +
  for sample in getSamples( sound ):
 +
    value = getValue( sample )
 +
    setSample( sample, value*2 )
 +
  return sound
 +
 +
def multiplyAmplitude( sound, factor ):
 +
  # multiply the value of each sample by provided factor
 +
  for sample in getSamples( sound ):
 +
    value = getValue( sample )
 +
    setSample( sample, value*factor )
 +
  return sound
 +
 +
def removeNoise( sound, threshold ):
 +
  # set all samples with values < threshold to 0
 +
  for sample in getSamples( sound ):
 +
    value = getValue( sample )
 +
    if abs( value ) < threshold:
 +
      setSample( sample, 0 )
 +
  return sound
 +
 +
def normalizeSound( sound ):
 +
  # makes the highest sample value equal to the max (32767)
 +
  list = []
 +
  for sample in getSamples( sound ):
 +
    list.append( abs( getValue( sample ) ) )
 +
  maxValue = max( list )
 +
  print "maxvalue = ", maxValue
 +
  for sample in getSamples( sound ):
 +
    value = getValue( sample )
 +
    setSample( sample, value*32767/maxValue )
 +
  return sound
 +
 
 +
def copyToOffset( sound, fromIndex, toIndex, whereIndex ):
 +
  # copies samples between fromIndex and toIndex to a new location
 +
  # starting at whereIndex
 +
  # Warning: this program is not robust and may crash if whereIndex is
 +
  # too large!
 +
  for i in range( fromIndex, toIndex ):
 +
    valueFrom = getSampleValueAt( sound, i )
 +
    valueWhere = getSampleValueAt( sound, i-fromIndex+whereIndex )
 +
    setSampleValueAt( sound, i-fromIndex+whereIndex,
 +
            valueFrom+valueWhere )
 +
  return sound
 +
 +
def copyToOffsetMultiply( sound, fromIndex, toIndex, whereIndex, factor ):
 +
  # copies samples between fromIndex and toIndex to a new location
 +
  # starting at whereIndex.  The samples are multiplied by factor while
 +
  # copied to their new place.
 +
  # Warning: this program is not robust and may crash if whereIndex is
 +
  # too large!
 +
  for i in range( fromIndex, toIndex ):
 +
    valueFrom = getSampleValueAt( sound, i )
 +
    valueWhere = getSampleValueAt( sound, i-fromIndex+whereIndex )
 +
    setSampleValueAt( sound, i-fromIndex+whereIndex,
 +
            ( valueFrom * factor )+valueWhere )
 +
  return sound
 +
</source>
 +
<br />
 +
 +
=JES Sound Functions=
 +
<br />
 +
This is just reference material taken from [http://www.csc.depauw.edu/~bhoward/courses/0304Winter/ref/ Depaw U.] that you may want to play with. 
 +
 +
 +
A sound is treated as a collection of sample values, much as a picture is a collection of pixels. Here are the functions on sounds:
 +
 +
<br />
 +
<br />
 +
<br />
 +
{|
 +
| width="30%" | '''makeSound'''(file) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 +
|Return a sound loaded from a WAV, AU, or AIFF file
 +
|-
 +
|'''makeEmptySound'''(sec)
 +
| Return a blank sound (all samples 0) of length sec seconds
 +
|-
 +
|'''writeSoundTo'''(s, file)
 +
| Save s in the given file; uses the same format as when loaded (makeEmptySound creates a sound in WAV format)
 +
|-
 +
|'''openSoundTool'''(s)
 +
| Open the sound exploration window for s
 +
|-
 +
|'''play'''(s)
 +
| Play sound s in the background
 +
|-
 +
| '''playAtRate'''(s, r)
 +
| Play s at speed r--1.0 is normal, 2.0 is twice as fast, etc.
 +
|-
 +
| '''playInRange'''(s, b, e)
 +
| Play s from sample number b to e
 +
|-
 +
| '''playAtRateInRange'''(s, r, b, e)
 +
| Play s from b to e at speed r
 +
|-
 +
| '''blockingPlay'''(s)
 +
| Play s and wait for it to finish (also, blockingPlayInRange and blockingPlayAtRateInRange)
 +
|-
 +
| '''getSamples'''(s)
 +
| Return the collection of samples in s (not quite a list, but indexable and usable in a for loop)
 +
|-
 +
| '''getLength'''(s)
 +
| Return the number of samples in s
 +
|-
 +
| '''getSamplingRate'''(s)
 +
| Return the number of samples per second in s
 +
|}
 +
 +
<br />
 +
<br />
 +
There are also some useful methods on sound and sample objects:
 +
<br />
 +
<br />
 +
{|
 +
|width="30%" | s.'''getSampleValue'''(i) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 +
| Return the (left channel, if stereo) value of the ith sample in s (the first sample is at index 1)
 +
|-
 +
| s.'''getLeftSampleValue'''(i)
 +
| Return the left channel value at index i
 +
|-
 +
| s.'''getRightSampleValue'''(i)
 +
| Return the right channel value at index i
 +
|-
 +
| s.'''setSampleValue'''(i, v)
 +
| Set the (left) value of sample i to v; the range of sample values is -32,768 to +32,767
 +
|-
 +
| s.'''setLeftSampleValue'''(i, v)
 +
| Same
 +
|-
 +
| s.'''setRightSampleValue'''(i, v)
 +
| Guess what?
 +
|-
 +
| s.'''getSampleObjectAt'''(i)
 +
| Extracts the sample object at index i, without creating a whole collection of samples
 +
|-
 +
| '''samp.value '''
 +
| Return the value of sample samp; change the value by assigning to this
 +
|-
 +
| '''samp.left'''
 +
| Return or change the left channel value of samp
 +
|-
 +
| '''samp.right '''
 +
| Return or change the right channel value of samp
 +
|}
 +
 +
<br />
 +
<br />
 +
Finally, JES provides a simple function to play a MIDI note:
 +
<br />
 +
<br />
 +
{|
 +
|width="30%" | '''playNote'''(n, dur, vol)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 +
|  plays note number n (middle C is 60, C-sharp is 61, etc.; the range is 0-127) for dur milliseconds at volume vol (maximum is 127).
 +
|}
 +
 +
The function pauses execution until the note is finished. For much more complete support of MIDI music, see the next section.
 +
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
[[Category:CSC111]][[Category:Python]][[Category:Jes]]

Latest revision as of 09:27, 24 February 2014

--D. Thiebaut (talk) 20:12, 23 February 2014 (EST)



SoundWave.jpg


Download Page




Videos



Physics of sound: A metal plate is connected to an oscillator and frequency is increased...


The source of waves] (1933). You may skip after the first 6 minutes.


  • Sound Tool
  • Increasing the amplitude of the signal (doubling)
  • Noise issue
  • Decreasing the amplitude of the signal.
  • Reducing the noise
  • Saturating/clipping the noise
  • Copying sound clip
  • Creating an echo


Reference


Installation


Sound Files


  • Get some sample wav files:


If you want to install JES on your personal Windows computer


If you want to install JES on your Windows laptop or computer, you can get Jes from the Google code web site. Grab the 3.2.1 version for Windows and install it on your Windows machine.

If you want to install JES on your personal Mac


Jes for the Mac is available on Google code. Get Jes 3.2.1 for the Mac, open the zip file, and move the JES 3.2.1.app to your Applications folder.

Example 1: Playing Sound Files

  • In the JES program area, type in the following main() function:


file = pickAFile()
sound = makeSound( file )
blockingPlay( sound )


  • Save the file as sound1.py
  • Click on Load Program
  • In the interactive area, type
  • When prompted for a sound file, select thisisatest.wav in the Sound Files folder.
  • Make sure the speakers are on, but not too loud and listen to the sentence being played.
  • Try one or two other sound files.



Part 3: Altering a sound file


  • You will reduce the intensity of the sound by dividing all the samples by half
  • Copy/Paste the program below in JES
  • Read it to make sure you understand it.


  # select  a sound file
  file = pickAFile()
  sound = makeSound( file )

  # play it
  blockingPlay( sound )

  # lower its intensity by half
  for i in range( 1, getLength( sound ) ):
     value = getSampleValueAt( sound, i )    # get the value of the i-th sample
     setSampleValueAt( sound, i, value / 2 )  # set the sample to half its original value

  # play new waveform back
  blockingPlay( sound )


Part 4: Reversing a Sound File

CSC111 lab3 sound1 sound2.png
  • The goal is to create 2 sound objects, sound1 and sound2 from the same file, and take the value of the sample at Index 1 in sound1 and to store it at Index N-1 in sound2. Identically for the sample at Index 2 which will go to Index N-2 in sound2.
  • Complete the table below and write down the relationship existing between i and j:




  i     j     i+j  
 1    
 2    
 3    
...    
N-2    
N-1    




  • From the table above extract the equation that yields j as a function of i
  • Write your for-loop to reverse sound1 into sound2
      N = ...
      for i in range( 1, N ):
           j = ...
           sample = getSampleValueAt( sound1, i )
           setSampleValueAt( sound2, j, sample )
  • Test your program by making it play sound1 first, then sound2.

Part 9: ECHO Echo echo

Same as Part 8, but now you will make 2 copies of your sound object, attenuate the first one by 0.5, the second one by 0.25, and delay each by 5000 from each other, and create a reverberation effect.



CSC111 Full Echo.png



Sample Functions


# sound1.py
# D. Thiebaut
# 3/23/09
# A collection of programs to treat and alter sound files

def doubleAmplitude( sound ):
  # increases the value of each sample by doubling it
  for sample in getSamples( sound ):
    value = getValue( sample )
    setSample( sample, value*2 )
  return sound

def multiplyAmplitude( sound, factor ):
  # multiply the value of each sample by provided factor
  for sample in getSamples( sound ):
    value = getValue( sample )
    setSample( sample, value*factor )
  return sound

def removeNoise( sound, threshold ):
  # set all samples with values < threshold to 0
  for sample in getSamples( sound ):
    value = getValue( sample )
    if abs( value ) < threshold:
      setSample( sample, 0 )
  return sound

def normalizeSound( sound ):
  # makes the highest sample value equal to the max (32767)
  list = []
  for sample in getSamples( sound ):
    list.append( abs( getValue( sample ) ) )
  maxValue = max( list )
  print "maxvalue = ", maxValue
  for sample in getSamples( sound ):
    value = getValue( sample )
    setSample( sample, value*32767/maxValue )
  return sound
  
def copyToOffset( sound, fromIndex, toIndex, whereIndex ):
  # copies samples between fromIndex and toIndex to a new location
  # starting at whereIndex
  # Warning: this program is not robust and may crash if whereIndex is
  # too large!
  for i in range( fromIndex, toIndex ):
    valueFrom = getSampleValueAt( sound, i )
    valueWhere = getSampleValueAt( sound, i-fromIndex+whereIndex )
    setSampleValueAt( sound, i-fromIndex+whereIndex, 
            valueFrom+valueWhere )
  return sound

def copyToOffsetMultiply( sound, fromIndex, toIndex, whereIndex, factor ):
  # copies samples between fromIndex and toIndex to a new location
  # starting at whereIndex.  The samples are multiplied by factor while 
  # copied to their new place.
  # Warning: this program is not robust and may crash if whereIndex is
  # too large!
  for i in range( fromIndex, toIndex ):
    valueFrom = getSampleValueAt( sound, i ) 
    valueWhere = getSampleValueAt( sound, i-fromIndex+whereIndex )
    setSampleValueAt( sound, i-fromIndex+whereIndex, 
            ( valueFrom * factor )+valueWhere )
  return sound


JES Sound Functions


This is just reference material taken from Depaw U. that you may want to play with.


A sound is treated as a collection of sample values, much as a picture is a collection of pixels. Here are the functions on sounds:




makeSound(file)                     Return a sound loaded from a WAV, AU, or AIFF file
makeEmptySound(sec) Return a blank sound (all samples 0) of length sec seconds
writeSoundTo(s, file) Save s in the given file; uses the same format as when loaded (makeEmptySound creates a sound in WAV format)
openSoundTool(s) Open the sound exploration window for s
play(s) Play sound s in the background
playAtRate(s, r) Play s at speed r--1.0 is normal, 2.0 is twice as fast, etc.
playInRange(s, b, e) Play s from sample number b to e
playAtRateInRange(s, r, b, e) Play s from b to e at speed r
blockingPlay(s) Play s and wait for it to finish (also, blockingPlayInRange and blockingPlayAtRateInRange)
getSamples(s) Return the collection of samples in s (not quite a list, but indexable and usable in a for loop)
getLength(s) Return the number of samples in s
getSamplingRate(s) Return the number of samples per second in s



There are also some useful methods on sound and sample objects:

s.getSampleValue(i)                Return the (left channel, if stereo) value of the ith sample in s (the first sample is at index 1)
s.getLeftSampleValue(i) Return the left channel value at index i
s.getRightSampleValue(i) Return the right channel value at index i
s.setSampleValue(i, v) Set the (left) value of sample i to v; the range of sample values is -32,768 to +32,767
s.setLeftSampleValue(i, v) Same
s.setRightSampleValue(i, v) Guess what?
s.getSampleObjectAt(i) Extracts the sample object at index i, without creating a whole collection of samples
samp.value Return the value of sample samp; change the value by assigning to this
samp.left Return or change the left channel value of samp
samp.right Return or change the right channel value of samp



Finally, JES provides a simple function to play a MIDI note:

playNote(n, dur, vol)         plays note number n (middle C is 60, C-sharp is 61, etc.; the range is 0-127) for dur milliseconds at volume vol (maximum is 127).

The function pauses execution until the note is finished. For much more complete support of MIDI music, see the next section.