I have created a script to play twinkle twinkle litte star with reference to this article (https://towardsdatascience.com/mathematics-of-music-in-python-b7d838c84f72) and created some of my changes. The music plays correctly, but there are some annoying beats in the background. Can some please help how to remove that annoying beats sound from the background?
My code:
import numpy as np
import pandas as pd
import os
from scipy.io.wavfile import write
class Music:
def __init__(self,notes,tempo,base_freq = 'C4'):
self.notes = notes
self.tempo = tempo
self.base_freq = base_freq
def generate_freq(self):
octave = ['C', 'c', 'D', 'd', 'E', 'F', 'f', 'G', 'g', 'A', 'a', 'B']
num = int(self.base_freq[1])
delta = 4 - num
bf = 261.63 * 2**(delta)
note_freqs = {octave[i]: bf * pow(2,(i/12)) for i in range(len(octave))}
note_freqs = {key : round(note_freqs[key],2) for key in note_freqs}
note_freqs[''] = 1.0 # silent note
return note_freqs
def generate_wave(self, freq):
sample_rate = 44100
div = int(sample_rate/freq)
freq = round(sample_rate/div,2)
amplitude = 4096
time = 60/self.tempo
t = np.linspace(0, time, int(sample_rate * time), endpoint=False)
wave = np.sin(2 * np.pi * freq * t)
wave *= 32767
return wave
def generate_digital_note(self):
note_freqs = self.generate_freq()
all_notes =[]
for i in range(len(self.notes)):
freq = note_freqs[self.notes[i]]
wave = [self.generate_wave(freq)]
all_notes = all_notes + wave
all_notes = np.concatenate(all_notes)
return all_notes
music_notes = 'C-C-G-G-A-A-G--F-F-E-E-D-D-C--G-G-F-F-E-E-D--G-G-F-F-E-E-D--C-C-G-G-A-A-G--F-F-E-E-D-D-C'
music_notes = music_notes.split('-')
twinkle_normal = Music(music_notes,120)
twinkle_normal_wave = twinkle_normal.generate_digital_note()
write('twinkle-twinkle_normal.wav', 44100, twinkle_normal_wave.astype(np.int16))
Thanks,
The signal that you generate has discontinuties at each note transition. Each discontinuity results in a "pop" of the speakers. A simple way to fix that is to multiply the array associated with each note by an envelope that rises from 0 to 1 at the beginning and falls from 1 to 0 at the end (i.e. provide an "attack" and "release" for the sound of each note).
Synth and DSP gurus will probably have much better suggestions--the possibilities are endless--but one quick way to do that is to use the Tukey window provided by scipy.signal.windows.tukey
. To try it, make two changes to your script:
from scipy.signal.windows import tukey
at the beginning.generate_wave()
, change this line:
wave = np.sin(2 * np.pi * freq * t)
to
wave = np.sin(2 * np.pi * freq * t) * tukey(len(t))