редактирование файлов WAV с использованием Python - PullRequest
4 голосов
/ 18 мая 2009

Между каждым словом в файле wav у меня полное молчание (я проверил в мастерской Hex, и молчание обозначено 0).

Как мне отключить звук без звука?

Я программирую, используя python.

Спасибо!

Ответы [ 6 ]

16 голосов
/ 18 мая 2009

Python имеет wav модуль . Вы можете использовать его, чтобы открыть файл wav для чтения, и использовать команду `getframes (1) ', чтобы просмотреть файл кадр за кадром.

import wave
w = wave.open('beeps.wav', 'r')
for i in range():
frame = w.readframes(1)

Возвращаемым фреймом будет строка байтов с шестнадцатеричными значениями. Если файл стереофонический, результат будет выглядеть примерно так (4 байта):

'\xe2\xff\xe2\xff'

Если его моно, он будет иметь половину данных (2 байта):

'\xe2\xff'

Каждый канал имеет длину 2 байта, потому что звук 16 бит. Если 8 бит, каждый канал будет только один байт. Вы можете использовать метод getsampwidth(), чтобы определить это. Кроме того, getchannels() будет определять его моно или стерео.

Вы можете перебрать эти байты, чтобы увидеть, все ли они равны нулю, что означает, что оба канала молчат. В следующем примере я использую функцию ord() для преобразования шестнадцатеричных значений '\xe2' в целые числа.

import wave
w = wave.open('beeps.wav', 'r')
for i in range(w.getnframes()):
    ### read 1 frame and the position will updated ###
    frame = w.readframes(1)

    all_zero = True
    for j in range(len(frame)):
        # check if amplitude is greater than 0
        if ord(frame[j]) > 0:
            all_zero = False
            break

    if all_zero:
        # perform your cut here
        print 'silence found at frame %s' % w.tell()
        print 'silence found at second %s' % (w.tell()/w..getframerate())

Стоит отметить, что один кадр молчания не обязательно обозначает пустое пространство, поскольку амплитуда может пересекать нулевые нормальные частоты. Поэтому рекомендуется, чтобы определенное количество кадров в 0 наблюдалось, прежде чем принимать решение о том, является ли регион фактически бесшумным.

5 голосов
/ 05 августа 2014

Я провел некоторое исследование по этой теме для проекта, над которым я работаю, и столкнулся с несколькими проблемами с предоставленным решением, а именно, метод определения молчания является неправильным. «Более правильной» реализацией будет:

import struct
import wave

wave_file = wave.open("sound_file.wav", "r")

for i in range(wave_file.getnframes()):
    # read a single frame and advance to next frame
    current_frame = wave_file.readframes(1)

    # check for silence
    silent = True
    # wave frame samples are stored in little endian**
    # this example works for a single channel 16-bit per sample encoding
    unpacked_signed_value = struct.unpack("<h", current_frame) # *
    if abs(unpacked_signed_value[0]) > 500:
        silent = False

    if silent:
        print "Frame %s is silent." % wave_file.tell()
    else
        print "Frame %s is not silent." % wave_file.tell()

Ссылки и полезные ссылки

*Struct Unpacking здесь будет полезно: https://docs.python.org/2/library/struct.html

** Хорошая ссылка, которую я нашел для объяснения формата волновых файлов для работы с битовыми кодировками разного размера и несколькими каналами: http://www.piclist.com/techref/io/serial/midi/wave.html

Использование встроенной функции ord () в Python для первого элемента строкового объекта, возвращаемого методом readframes (x), будет работать некорректно.

Другим ключевым моментом является то, что многоканальное аудио чередуется, и поэтому для работы с каналами требуется немного дополнительной логики. Опять же, ссылка выше подробно описывает это.

Надеюсь, это поможет кому-то в будущем.

Вот некоторые наиболее важные моменты из ссылки и то, что я нашел полезным.

Организация данных


Все данные хранятся в 8-битных байтах в формате Intel 80x86 (т.е. с прямым порядком байтов). Байты многобайтовых значений сначала сохраняются младшими (то есть наименее значимыми) байтами. Биты данных имеют следующий вид (т. Е. Показаны с номерами бит вверху):

         7  6  5  4  3  2  1  0
       +-----------------------+
 char: | lsb               msb |
       +-----------------------+

         7  6  5  4  3  2  1  0 15 14 13 12 11 10  9  8
       +-----------------------+-----------------------+
short: | lsb     byte 0        |       byte 1      msb |
       +-----------------------+-----------------------+

         7  6  5  4  3  2  1  0 15 14 13 12 11 10  9  8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
       +-----------------------+-----------------------+-----------------------+-----------------------+
 long: | lsb     byte 0        |       byte 1          |         byte 2        |       byte 3      msb |
       +-----------------------+-----------------------+-----------------------+-----------------------+

Чередование


Для многоканальных звуков (например, стереофонического сигнала) чередуются отдельные точки выборки из каждого канала. Например, предположим стереофоническую (т.е. двухканальную) форму волны. Вместо того, чтобы сначала сохранить все точки выборки для левого канала, а затем сохранить все точки выборки для правого канала, вы «смешиваете» точки выборки двух каналов вместе. Вы бы сохранили первую точку выборки левого канала. Далее вы должны сохранить первую точку выборки правого канала. Далее вы должны сохранить вторую точку выборки левого канала. Затем вы должны сохранить вторую точку выборки правого канала и т. Д., Чередуя хранение следующей точки выборки каждого канала. Это то, что подразумевается под чередованными данными; Вы сохраняете следующую точку выборки каждого из каналов по очереди, так что точки выборки, которые должны быть «воспроизведены» (т.е. отправлены в ЦАП) одновременно, сохраняются непрерывно.

2 голосов
1 голос
/ 18 мая 2009

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

Python не очень хороший инструмент для решения подобных задач. (

1 голос
/ 18 мая 2009

Возможно, вы захотите попробовать sox , инструмент для обработки звука в командной строке. У него много режимов, один из них silence:

silence: удаляет тишину в начале, середине или конце звукового файла. Молчание - это все, что ниже указанного порога.

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

Чтобы удалить тишину из середины файла, укажите below_periods, который является отрицательным. Это значение затем обрабатывается как положительное значение и также используется для указания того, что эффект должен возобновить обработку, как указано above_periods, что делает его подходящим для удаления периодов молчания в середине звукового файла.

Я не нашел ни одного сборочного Python для libsox, но Вы можете использовать его, так как Вы используете все программы командной строки в Python (или Вы можете переписать его - тогда используйте источники sox для руководства).

1 голос
/ 18 мая 2009

У меня нет опыта в этом, но посмотрите на модуль wave , присутствующий в стандартной библиотеке. Это может делать то, что вы хотите. В противном случае вам придется читать файл как поток байтов и вырезать последовательности из 0 байтов (но вы не можете просто вырезать все 0 байтов, так как это сделает файл недействительным ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...