Написание wav файла в Python с помощью wavfile.write от SciPy

У меня есть этот код:

import numpy as np
import scipy.io.wavfile
import math

rate, data = scipy.io.wavfile.read('xenencounter_23.wav')

data2 = []

for i in range(len(data)):
    data2.append([int(round(math.sin(data[i][0])*3000)), int(round(math.sin(data[i][1])*3000))])

data2 = np.asarray(data2)

print data2

scipy.io.wavfile.write('xenencounter_23sin3.wav',rate,data2)

Отпечатает (усечен):

[[-2524  2728]
 [ -423 -2270]
 [ 2270   423]
 ..., 
 [-2524     0]
 [ 2524 -2728]
 [-2270   838]]

Wav файл открывается и воспроизводится в проигрывателе Windows Media, поэтому, по крайней мере, его правильный формат. Однако, открывая его Audacity и глядя на отдельные сэмплы, все они равны 0, и, соответственно, файл вообще не воспроизводит звук.

То, что я не понимаю, это то, как этот массив numpy, указанный выше, становится все 0. Он должен быть ниже максимального значения для образца (или выше, если он отрицательный).

Ответ 1

Я обнаружил, что scipy.io.wavfile.write() записывает в 16-разрядное целое число, что объясняет большие размеры файлов при попытке использовать 32-разрядное целое (по умолчанию). Хотя я не мог найти способ изменить это в wavfile.write, я нашел это, изменив:

data2 = np.asarray(data2)

к

data2 = np.asarray(data2, dtype=np.int16)

Я мог бы написать рабочий файл.

Ответ 2

При создании wav файлов через scipy.io.wavfile.write() я обнаружил, что амплитуда очень важна. если вы создадите синусоидальную волну с амплитудой 150, это звучит как тишина при воспроизведении в VLC. если амплитуда равна 100, это звучит как искаженная синусоидальная волна, и если вы делаете ее 80, она начинает звучать как обычный файл.

Определенно нужно быть осторожным в отношении амплитуды при создании волновых файлов, но теперь мне не ясно, что такое максимальный уровень, прежде чем он начнет отсекать или исчезать.

Ответ 3

Как вы обнаружили, распечатывая вывод в разных точках и повторно сохраняя то, что вы первоначально загрузили, строка data2.append([int(round(math.sin(data[i][0])*3000)), int(round(math.sin(data[i][1])*3000))]) является источником проблемы.

Я подозреваю, что 3000 слишком большой амплитуды. Попробуйте 1.