====== 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 ===== 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!