File size: 2,500 Bytes
360737a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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)