Запись wav файла дает звуки щелчка - PullRequest
0 голосов
/ 30 мая 2018

У меня есть этот код для создания wav-файла:

class Note:
    def __init__(self,name,octave,duration):
        self.name = name
        self.octave = octave
        self.duration = duration

SAMPLE_RATE = 44100

wav = wave.open("starw.wav", mode="w")
wav.setparams((1, 2, SAMPLE_RATE , SAMPLE_RATE*4, 'NONE', 'noncompressed'))

def generate_sample(note,volume):
    freq = FREQUENCIES[note.octave][note.name]
    duration = note.duration
    total_samples = int(SAMPLE_RATE * duration)
    for i in range(0,total_samples):
        s = np.clip(int((volume)*math.sin(freq*math.pi*float(i)/float(SAMPLE_RATE))),-32768,32768)    
        data = struct.pack('<h',s)
        wav.writeframes(data)

    return data

for i,m in enumerate(melody):

    if i<len(melody)/5:
        generate_sample(m, 100+i*500)
    elif len(melody)/5<=i<=4*len(melody)/5:
        generate_sample(m, 8800)
    else:
        generate_sample(m, 8800-i*20)

Здесь FREQUENCIES - это диктант, описывающий примечания и их частоты.melody - это массив Note объектов.Все работает отлично, за исключением того факта, что странные звуки щелчка производятся во время пауз.Насколько я понял, это как-то связано с частотой дискретизации.Но я не знаю, как изменить свой код, чтобы избежать пауз.Вот мелодия: https://drive.google.com/open?id=1e03VC90w5WF4QdU-VxrV906dl_c3UvSQ

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Если вы имеете в виду неприятные щелчки между нотами: это совершенно нормально.

Даже в языках программирования, которые были специально разработаны для создания музыки, этот эффект возникает, если вы просто сопоставляете блоки с (синусоидальными) волнамикоторые имеют некоторую фиксированную амплитуду в течение всей продолжительности.

Вот эскиз того, как это выглядит, когда заканчивается одна нота, и начинается следующая нота:

enter image description here

Если первый узел случайно не заканчивается ровно в ноль, вы услышите этот «скачок», который наносится на 2.

Чтобы избежать этого, вы должны реализовать лучшесинтез ноты.

Простым решением было бы плавное увеличение амплитуды каждой ноты, а затем плавное затухание в конце.Вот как будет выглядеть переход между двумя примечаниями, если вы сделаете это:

enter image description here

Этот график был создан по следующей формуле:

  if x > 2:
    return sin((x-2) * 60) * (1 - exp(-(x-2)**2 / 0.5))
  else:
    return sin(x * 30) * (1- exp(-(x-2)**2 / 0.5))

Надеемся, что вы можете распознать (1 - exp(-(x - tClick) ** 2 / smoothness)) факторы "размягчения", которые ответственны за нарастание / затухание.

Но опять же вы видите, что промежутки между нотами увеличиваютсяи если вы затем попытаетесь пересечь интервалы между различными примечаниями, все это станет довольно запутанным и сложным, и вам, вероятно, лучше взять язык программирования или библиотеку, которая уже знает, как это сделать правильно.Я думаю, что Руководство Чака содержало довольно подробное объяснение того, как получить все более и более звучащие ноты.

0 голосов
/ 30 мая 2018

Если бы я догадался, я бы подумал, что это может быть связано с тем фактом, что длины нот иногда даже не кратны частоте нот.В результате sin(end_time) примечания может иногда приводить к относительно большому значению: 32768 в худшем случае.Внезапное падение громкости на этой частоте может быть причиной слышимого щелкающего / хихикающего шума.

Завершение нот только тогда, когда значение int((volume)*math.sin(freq*math.pi*float(i)/float(SAMPLE_RATE))) достигает значения, близкого к 0, устранит большую часть этого шума,если это так.

...