interactive-pipe-audio-xylo / synthetizer.py
balthou's picture
xylo player
360737a
import numpy as np
NOTE_FREQUENCIES = {
'C4': 261.63, # Middle C
'D4': 293.66,
'E4': 329.63,
'F4': 349.23,
'G4': 392.00,
'A4': 440.00,
'B4': 493.88,
'C5': 523.25
}
# from pydub import AudioSegment
# import simpleaudio as sa
def generate_sine_wave(frequency, duration, sample_rate=44100, amplitude=0.5):
"""
Generate a sine wave for a given frequency, duration, and sample rate.
"""
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
wave = amplitude * np.sin(2 * np.pi * frequency * t)
return wave
def apply_decay(wave, decay_factor=0.0001):
"""
Apply an exponential decay to the waveform to simulate the damping effect.
"""
decay = np.exp(-decay_factor * np.arange(len(wave)))
return wave * decay
def create_xylophone_note(frequency, duration=0.5, sample_rate=44100):
"""
Create a synthesized xylophone note using sine waves and damping.
"""
# Generate the fundamental frequency
wave = generate_sine_wave(frequency, duration, sample_rate)
# Add overtones (harmonics) to mimic the xylophone's metallic timbre
overtone1 = generate_sine_wave(
frequency * 2.5, duration, sample_rate, amplitude=0.3)
overtone2 = generate_sine_wave(
frequency * 4.0, duration, sample_rate, amplitude=0.2)
# Combine the fundamental frequency and overtones
combined_wave = wave + overtone1 + overtone2
# Apply decay to simulate the note fading out
combined_wave = apply_decay(combined_wave)
# Normalize to 16-bit range and convert to audio segment
# audio_data = (combined_wave * 32767).astype(np.int16)
audio_data = combined_wave
return audio_data
# audio_segment = AudioSegment(audio_data.tobytes(
# ), frame_rate=sample_rate, sample_width=2, channels=1)
# return audio_segment
# def play_note(note):
# """
# Play a given AudioSegment note using simpleaudio.
# """
# play_obj = sa.play_buffer(
# note.raw_data, num_channels=1, bytes_per_sample=2, sample_rate=note.frame_rate)
# play_obj.wait_done()
def get_note(note: str) -> np.ndarray:
# Example usage to create and play a sequence of xylophone notes
return create_xylophone_note(NOTE_FREQUENCIES.get(note, 'C4'))
# Generate and play each note
# for note_name, frequency in note_frequencies.items():
# print(f"Playing {note_name}")
# note = create_xylophone_note(frequency)
# play_note(note)