Форум сайта python.su
Здравствуйте, стандартные модули для работы с wav (wave) и методы в scikits.audiolab wavwrite позволяют записывать данные в wav файл но при этом указанный файл будет перезаписан. Существует ли способ дописать новые данные в конец уже существующего wav файла?
Офлайн
Можно попробовать например считать данные из файла в память, дополнить их необхрдимыми, а потом записать в файл.
Так как структура wave не особа сложна, можно и руками все дописать., но наверное вам этот вариант не понравится.
Офлайн
Благодарю за ответ ) Но есть нюанс. Мы производим много часовые записи за это время Python съедает всю доступную оперативную память. Выход был найден с помощью модуля multiprocessing. Во время работы скрипта создается под процесс, который записывает данные с микрофона в wav файл после своей работы - под процесс уничтожается главным процессом скрипта. Занимаемая оперативная память освобождается. Затем вызывается новый под процесс. Таким образом мы получили возможность производить много часовую запись на диск, с постоянным уровнем потребляемой оперативной памяти. Если мы будем загружать каждый файл в оперативную память для того, чтобы их объединить тогда все ранее записанные файлы будут сидеть в памяти интерпретатора и потреблять оперативную память. К сожалению такой подход нам не походит. Было бы здорово дозаписывать данные в конец wav файлов/
Отредактировано med_phisiker (Фев. 1, 2013 12:05:03)
Офлайн
med_phisiker
если в кратце, то нужно открыть исходный файл для записи, дополнительный файл для чтений, в цикле пишете значения из одного в другой, после этого в первом перезаписывайте пару байт отвечающих за общий размер наборов данных. Могу не точно говорить, ибо последний раз этим занимался добрым 5 лет назад, нужно смотреть на структуру wave.
А вообще, судя по тому как вы пишите, у вас там все как то не правильно утсроено. Многочасовые записи в память - это возможно в случае если у вас сервер обработки данных с гигабайтами озу. и мульти процессинг тут в общем то кривоватый обходной путь. Займитесь лучше усовершенствованием вашего исходного кода, запомните что такое ссылка на объект, что есть области видимости, а также del и модуль gc.
Офлайн
У нас однопалатный компьютер с 500 МГц и 500 мб ОЗУ. del и gc не дают нужного результата, при их использовании память все равно остается у интерпретатора. А создание и уничтожение под процесса освобождает ее полностью благодаря этому скрипт постоянно потребляет всего 100 мб оперативной памяти и этот уровень остается постоянным. Судя по достигнутому результату это правильный подход )
Мы так же попробовали выделять память на прямую и потом уничтожать ее встроенными средствам подобными языку С (http://docs.python.org/2/c-api/memory.html). Но таким образом у в интерпретаторе все равно оставалась часть занятой памяти. А с последовательно запускаемыми под процессами мы получили постоянный уровень потребляемой памяти. Благодарю за ответ, хотелось бы получить ссылку (или пример кода) демонстрирующую запись данных в конец уже существующего wav файла.
Отредактировано med_phisiker (Фев. 2, 2013 10:25:14)
Офлайн
знаете,мы с вами, наверное,работаем в смежных или родственных областях. я свой одноплатный пк получу в лучшем случае через 2 месяца - либо его и вправду в москве нету либо отдел закупок плохо делает свое дело.
хотя у меня есть личный пк raspberry pi, но его мощносьи не хватает для задачи.
у меня счаз мало времени, если не сильно к спеху то через 3-4 дня я думвю нвпишу такой код.
Офлайн
нет проблем пишите когда вам удобно, заранее благодарен )
Офлайн
Итак, вот структура
Ниже рабочий код, решение “в лоб”, показывающее как можно имея два файла слепить третий из двух. Прикреплен архив с пробными файлами.
#!/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()
Прикреплённый файлы:
wave.tar.gz (8,1 KБ)
Офлайн
Спасибо, буду разбираться )
Офлайн
Немного вмешаюсь. Мне кажется стратегия записи очень длинных данных именно в wav файл не очень удачна. Он при записи на диск вообще не жмется и есть много вариантов как он будет записываться. Такие длинные записи наверное нужны вам для анализа или последующей обработки. Я для записи таких данных практикую укладывание данных в формат hdf5. Он от рождения поддерживает дозапись данных. Но его лучше использовать с буферизацией. Т.е. бросать данные блоками. Проблем с памятью при таком подходе вообще нет. И упаси боже - мультипроцессинг тут вообще не нужен. (правда с большими объемами данных не работал максимум 20-30 Gb)
При использовании hdf5 легко будет перейти на запись с более высокими показателями сжатия.
Отредактировано doza_and (Фев. 3, 2013 14:08:05)
Офлайн