Найти - Пользователи
Полная версия: дописать данные в wav файл
Начало » Python для экспертов » дописать данные в wav файл
1 2
med_phisiker
Здравствуйте, стандартные модули для работы с wav (wave) и методы в scikits.audiolab wavwrite позволяют записывать данные в wav файл но при этом указанный файл будет перезаписан. Существует ли способ дописать новые данные в конец уже существующего wav файла?
JOHN_16
Можно попробовать например считать данные из файла в память, дополнить их необхрдимыми, а потом записать в файл.
Так как структура wave не особа сложна, можно и руками все дописать., но наверное вам этот вариант не понравится.
med_phisiker
Благодарю за ответ ) Но есть нюанс. Мы производим много часовые записи за это время Python съедает всю доступную оперативную память. Выход был найден с помощью модуля multiprocessing. Во время работы скрипта создается под процесс, который записывает данные с микрофона в wav файл после своей работы - под процесс уничтожается главным процессом скрипта. Занимаемая оперативная память освобождается. Затем вызывается новый под процесс. Таким образом мы получили возможность производить много часовую запись на диск, с постоянным уровнем потребляемой оперативной памяти. Если мы будем загружать каждый файл в оперативную память для того, чтобы их объединить тогда все ранее записанные файлы будут сидеть в памяти интерпретатора и потреблять оперативную память. К сожалению такой подход нам не походит. Было бы здорово дозаписывать данные в конец wav файлов/
JOHN_16
med_phisiker
если в кратце, то нужно открыть исходный файл для записи, дополнительный файл для чтений, в цикле пишете значения из одного в другой, после этого в первом перезаписывайте пару байт отвечающих за общий размер наборов данных. Могу не точно говорить, ибо последний раз этим занимался добрым 5 лет назад, нужно смотреть на структуру wave.

А вообще, судя по тому как вы пишите, у вас там все как то не правильно утсроено. Многочасовые записи в память - это возможно в случае если у вас сервер обработки данных с гигабайтами озу. и мульти процессинг тут в общем то кривоватый обходной путь. Займитесь лучше усовершенствованием вашего исходного кода, запомните что такое ссылка на объект, что есть области видимости, а также del и модуль gc.

med_phisiker
У нас однопалатный компьютер с 500 МГц и 500 мб ОЗУ. del и gc не дают нужного результата, при их использовании память все равно остается у интерпретатора. А создание и уничтожение под процесса освобождает ее полностью благодаря этому скрипт постоянно потребляет всего 100 мб оперативной памяти и этот уровень остается постоянным. Судя по достигнутому результату это правильный подход )
Мы так же попробовали выделять память на прямую и потом уничтожать ее встроенными средствам подобными языку С (http://docs.python.org/2/c-api/memory.html). Но таким образом у в интерпретаторе все равно оставалась часть занятой памяти. А с последовательно запускаемыми под процессами мы получили постоянный уровень потребляемой памяти. Благодарю за ответ, хотелось бы получить ссылку (или пример кода) демонстрирующую запись данных в конец уже существующего wav файла.
JOHN_16
знаете,мы с вами, наверное,работаем в смежных или родственных областях. я свой одноплатный пк получу в лучшем случае через 2 месяца - либо его и вправду в москве нету либо отдел закупок плохо делает свое дело.
хотя у меня есть личный пк raspberry pi, но его мощносьи не хватает для задачи.
у меня счаз мало времени, если не сильно к спеху то через 3-4 дня я думвю нвпишу такой код.
med_phisiker
нет проблем пишите когда вам удобно, заранее благодарен )
JOHN_16
Итак, вот структура
Ниже рабочий код, решение “в лоб”, показывающее как можно имея два файла слепить третий из двух. Прикреплен архив с пробными файлами.

#!/usr/bin/python
# -*- coding: utf-8 -*-
import struct, shutil
from pprint import pprint
#===============================================================================
# Прочтем и выведим на экран содержимое заголовка wav файла
#===============================================================================
f_in_one=open('Sound1.wav', 'rb')
binary_string=f_in_one.read(12)
riff_chunk_ID,riff_chunk_cksize,WAVEID=struct.unpack('<4si4s', binary_string)
binary_string=f_in_one.read(8)
fmt_chunk_ID, fmt_chunk_size=struct.unpack('<4si', binary_string)
binary_string=f_in_one.read(fmt_chunk_size)
fmt_wFormatTag, fmt_nChannels, fmt_nSamplesPerSec,fmt_nAvgBytesPerSec,fmt_nBlockAlign,fmt_wBitsPerSample\
=struct.unpack('<hhiihh', binary_string)
binary_string=f_in_one.read(8)
data_chunk_ID,data_chunk_size=struct.unpack('<4si', binary_string)
pprint(locals())
#===============================================================================
# Прочтем только нужные поля во втором файле
#===============================================================================
f_in_two=open('Sound2.wav', 'rb')
f_in_two.seek(36)
binary_string=f_in_two.read(8)
fit_data_chunk_id, fit_data_chunk_size=struct.unpack('<4si', binary_string)
if fit_data_chunk_id!='data':
    raise Exception('data chunk not found, perhaps header size is another')
#===============================================================================
# Подготавливаем выходной файл
#===============================================================================
shutil.copy('Sound1.wav', 'Sound3.wav')
f_out=open('Sound3.wav', 'rb+')
f_out.seek(0, 2)
#===============================================================================
# Копируем содержимое
#===============================================================================
buffer_length=1024*1024
while True:
    binary_string=f_in_two.read(buffer_length)
    if binary_string=='':
        break
    f_out.write(binary_string)
# Изменяем определенные поля, отвечающие за размер chunk'ов
f_out.flush()
f_out.seek(4)
f_out.write(struct.pack('<i', (riff_chunk_cksize+fit_data_chunk_size)))
f_out.seek(40)
f_out.write(struct.pack('<i', (data_chunk_size+fit_data_chunk_size)))
f_in_one.close()
f_in_two.close()
f_out.close()
med_phisiker
Спасибо, буду разбираться )
doza_and
Немного вмешаюсь. Мне кажется стратегия записи очень длинных данных именно в wav файл не очень удачна. Он при записи на диск вообще не жмется и есть много вариантов как он будет записываться. Такие длинные записи наверное нужны вам для анализа или последующей обработки. Я для записи таких данных практикую укладывание данных в формат hdf5. Он от рождения поддерживает дозапись данных. Но его лучше использовать с буферизацией. Т.е. бросать данные блоками. Проблем с памятью при таком подходе вообще нет. И упаси боже - мультипроцессинг тут вообще не нужен. (правда с большими объемами данных не работал максимум 20-30 Gb)
При использовании hdf5 легко будет перейти на запись с более высокими показателями сжатия.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB