Python: изменение тональности аудиофайла
Это мой первый пост в стеке. До сих пор этот сайт был очень полезным, но я новичок и нуждаюсь в ясном объяснении своей проблемы, что связано с тональным сдвигом звука в Python. У меня установлены текущие модули: numpy, scipy, pygame и scikits "samplerate" api.
Моя цель - взять стереофайл и воспроизвести его на другом шаге за несколько шагов. В настоящее время я загружаю файл в массив с помощью pygame.sndarray, затем применяю преобразование сэмплера, используя scikits.samplerate.resample, а затем преобразовываю вывод обратно в звуковой объект для воспроизведения с помощью pygame. Проблема заключается в том, что звук из мусора выходит из моих динамиков. Конечно, я пропускаю несколько шагов (кроме того, что не знаю ничего о математике и аудио).
Спасибо.
import time, numpy, pygame.mixer, pygame.sndarray
from scikits.samplerate import resample
pygame.mixer.init(44100,-16,2,4096)
# choose a file and make a sound object
sound_file = "tone.wav"
sound = pygame.mixer.Sound(sound_file)
# load the sound into an array
snd_array = pygame.sndarray.array(sound)
# resample. args: (target array, ratio, mode), outputs ratio * target array.
# this outputs a bunch of garbage and I don't know why.
snd_resample = resample(snd_array, 1.5, "sinc_fastest")
# take the resampled array, make it an object and stop playing after 2 seconds.
snd_out = pygame.sndarray.make_sound(snd_resample)
snd_out.play()
time.sleep(2)
Ответы
Ответ 1
Ваша проблема в том, что pygame работает с массивами numpy.int16
, но вызов resample
возвращает массив numpy.float32
:
>>> snd_array.dtype
dtype('int16')
>>> snd_resample.dtype
dtype('float32')
Вы можете преобразовать результат resample
в numpy.int16
с помощью astype
:
>>> snd_resample = resample(snd_array, 1.5, "sinc_fastest").astype(snd_array.dtype)
С помощью этой модификации ваш питон script воспроизводит файл tone.wav
красиво, с более низким шагом и более низкой скоростью.
Ответ 2
Лучше всего, наверное, использовать аудиторию python.
Вот ссылка, я использовал ее, чтобы сделать то же самое, это очень просто, просто прочитайте всю документацию.
http://audiere.sourceforge.net/home.php
Ответ 3
Скорее всего, scikits.samplerate.resample "думает", что ваш звук находится в другом формате, чем 16-битный стерео. Проверьте документацию на scikits.samplerate, где выбрать правильный формат звука в вашем массиве -
Если он передискретировал 16-битный звук, рассматривая его как 8-битный мусор, что бы вышло.
Ответ 4
Из документации scikits.samplerate.resample
:
Если вход имеет ранг 1, все данные используются, и предполагается, что они получены из моносигнала. Если rank равно 2, числовые столбцы будут считаться количеством каналов.
Итак, я думаю, что вам нужно сделать что-то подобное, чтобы передать стерео данные в resample
в ожидаемом формате:
snd_array = snd_array.reshape((-1,2))
snd_resample = resample(snd_array, 1.5, "sinc_fastest")
snd_resample = snd_resample.reshape(-1) # Flatten it out again