Table of Contents
Creating a Sine Wave Tone Generator in Python
Objective: The `tone_generator` script aims to generate a sine wave tone of a specified frequency and duration, and play it through the default audio output device.
App
- tone_generator.py
import numpy as np import pyaudio import argparse def generate_tone(frequency, duration, sample_rate=44100, volume=0.5): # Generate the time axis t = np.linspace(0, duration, int(sample_rate * duration), False) # Generate the sine wave tone = volume * np.sin(2 * np.pi * frequency * t) # Ensure that we have the correct format tone = np.int16(tone * 32767) # Initialize PyAudio p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paInt16, channels=1, rate=sample_rate, output=True) # Play the tone stream.write(tone.tobytes()) # Cleanup stream.stop_stream() stream.close() p.terminate() if __name__ == "__main__": parser = argparse.ArgumentParser(description="Generate a sine wave tone of a specific frequency.") parser.add_argument("frequency", type=float, help="Frequency of the sine wave in Hz.") parser.add_argument("duration", type=float, help="Duration of the tone in seconds.") args = parser.parse_args() generate_tone(args.frequency, args.duration)
Script Overview:
- Filename: `tone_generator.py` - Dependencies: `numpy`, `pyaudio` - Functions:
1. `generate_tone(frequency, duration, sample_rate=44100, volume=0.5)`: Generates and plays a sine wave tone of a specified frequency and duration.
Script Execution:
1. Import Dependencies:
- The script imports the necessary libraries, including `numpy` for numerical operations and `pyaudio` for audio playback.
2. Generate Tone:
- The `generate_tone` function creates a time axis using `numpy.linspace` and then generates a sine wave based on the specified frequency.
- The sine wave is scaled and converted to a 16-bit integer format for compatibility with `pyaudio`.
3. Initialize PyAudio:
- `pyaudio.PyAudio()` initializes the audio system.
- The audio stream is opened with the correct format (16-bit, 1 channel, sample rate of 44100 Hz).
4. Play Tone:
- The generated tone is played through the default audio output device using `stream.write`.
5. Cleanup:
- The audio stream is stopped and closed, and the `PyAudio` instance is terminated to free resources.
6. Command Line Interface:
- The script uses `argparse` to parse command-line arguments for frequency and duration, allowing users to specify these parameters when running the script.
Script Execution:
- To execute the script, run the `tone_generator.py` file with the desired frequency and duration as arguments.
- Ensure that the required dependencies (`numpy`, `pyaudio`) are installed.
- Example usage: `python tone_generator.py 500 5` will generate a 500 Hz tone for 5 seconds.
- Any errors encountered during execution are reported to the user for troubleshooting.
Final Note: The `tone_generator` script provides a simple and flexible way to generate and play sine wave tones of various frequencies and durations, making it useful for testing audio equipment or creating sound effects.
Plot
In this section, we'll explore how to visualize the generated sine wave tone using matplotlib. Here's the modified script:
import numpy as np import pyaudio import matplotlib.pyplot as plt import argparse def generate_tone(frequency, duration, sample_rate=44100, volume=0.5): t = np.linspace(0, duration, int(sample_rate * duration), False) tone = volume * np.sin(2 * np.pi * frequency * t) tone = np.int16(tone * 32767) p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paInt16, channels=1, rate=sample_rate, output=True) stream.write(tone.tobytes()) stream.stop_stream() stream.close() p.terminate() return t, tone def plot_tone(frequency, duration): t, tone = generate_tone(frequency, duration) plt.figure(figsize=(10, 4)) plt.plot(t[:1000], tone[:1000]) # Plot first 1000 samples for clarity plt.title(f'Sine Wave - {frequency} Hz') plt.xlabel('Time [s]') plt.ylabel('Amplitude') plt.grid(True) plt.show() if __name__ == "__main__": parser = argparse.ArgumentParser(description="Generate and plot a sine wave tone of a specific frequency.") parser.add_argument("frequency", type=float, help="Frequency of the sine wave in Hz.") parser.add_argument("duration", type=float, help="Duration of the tone in seconds.") parser.add_argument("--plot", action="store_true", help="Plot the generated tone.") args = parser.parse_args() if args.plot: plot_tone(args.frequency, args.duration) else: generate_tone(args.frequency, args.duration)
This script will generate the sine wave tone and, if the `–plot` flag is provided, it will also plot the first 1000 samples of the generated tone. Let me know if you need further assistance!
