Python: изменить высоту звукового файла - PullRequest
10 голосов
/ 14 декабря 2011

это мой первый пост в стеке.До сих пор этот сайт был очень полезным, но я новичок и нуждаюсь в четком объяснении моей проблемы, которая связана со звуком со смещением высоты звука в Python.У меня установлены текущие модули: numpy, scipy, pygame и scipits api "samplerate".

Моя цель - взять стереофонический файл и воспроизводить его с разной высотой тона за как можно меньшее количество шагов.В настоящее время я загружаю файл в массив, используя 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)

Ответы [ 4 ]

11 голосов
/ 22 декабря 2011

Ваша проблема в том, что 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)

С этой модификацией ваш скрипт на python прекрасно воспроизводит файл tone.wav с меньшей высотой и скоростью.

3 голосов
/ 15 декабря 2011

Ваша лучшая ставка, вероятно, использовать Python Audiere.

Вот ссылка, я использовал ее для того же, очень просто, просто прочитайте всю документацию.

http://audiere.sourceforge.net/home.php

0 голосов
/ 16 декабря 2011

Из документации 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
0 голосов
/ 14 декабря 2011

Скорее всего, scikits.samplerate.resample «думает», что ваш звук в другом формате, чем 16-битное стерео.Обратитесь к документации на scikits.samplerate, где выбрать правильный аудиоформат в вашем массиве. Если 16-битное аудио будет пересчитано, то получится 8-битный мусор.

...