Robin Andrews
Robin Andrews

Reputation: 3804

Python playTone(freq, duration) command for Learning and Teaching

I'm really baffled by this. I asked a few years back how to generate a tone with Python using something like playTone(freq, duration) and was overwhelmed by the complexity of the responses, and the lack of any simple solution.

The winsound module is inadequate as it trips over itself after a few notes, and is too limited in other ways (maybe 2 notes at a time would be nice, or a choice of wave types).

As a teacher, it makes a huge amount of sense to me to use sound to illustrate programming principles such as loops and randomness, as many people are auditory learners.

This kind of thing was incredibly simple with early home computers running Basic, where you could create 4 channel master pieces with ease. I just don't understand why such a thing isn't easily available with Python, which is meant to be a so well suited to learners.

JavaScript now can do this relatively easily with the audio context and its oscillators, but I want to use Python, and in particular to combine the visual power and simplicity of turtle graphics with an auditory component that doesn't require in depth knowledge of computer hardware and physics to produce.

Can anyone help me to find a simple up-to-date (late 2016) solution for this please?

Upvotes: 0

Views: 1935

Answers (1)

Anil_M
Anil_M

Reputation: 11473

There are various ways to do it. Here is an simple implementation using pyaudio module.

You can install pyaudio using
pip install pyaudio #for windows and
sudo apt-get install python-pyaudio #For linux

Following program has playTone function that gets two inputs; frequency and duarion. You can vary those to get the desired audible frequency tones and "bearable" duration.

If you are planning to create multi-channel complex audio , then you may want to look into pygame. There are ample examples on SO for that.

import pyaudio
import math




def playTone( freq , length): 

    bit_rate = 16000 #number of frames per second/frameset.      

    frequency = freq #in Hz, waves per second
    play_time = length #in seconds to play sound

    if frequency > bit_rate:
        bit_rate = frequency+100

    num_frames = int(bit_rate * play_time)
    total_frames = num_frames % bit_rate
    wave_info = ''    

    for x in xrange(num_frames):
     wave_info = wave_info+chr(int(math.sin(x/((bit_rate/frequency)/math.pi))*127+128))    

    for x in xrange(total_frames): 
     wave_info = wave_info+chr(128)

    p = PyAudio()
    stream = p.open(format = p.get_format_from_width(1), 
                    channels = 1, 
                    rate = bit_rate, 
                    output = True)

    stream.write(wave_info)
    stream.stop_stream()
    stream.close()
    p.terminate()



if __name__ == '__main__':
    frequency = 1500 #Hz
    duration = 2 #seconds

    PyAudio = pyaudio.PyAudio

    #Function to play frequency for given duration
    playTone(frequency , duration)

Upvotes: 1

Related Questions