Как создать файл WAV из поля sqlite BLOB с помощью python

Я получаю BLOB-объект из базы данных MS Access, которая содержит монофонические данные WAV с инструмента. Это всего 1 секунда. Он начинается с разных значений, поэтому я имею в виду, что это чистые данные wav.

b'\\f_?\xb2\xca^??;]?\xa9(Z?\xf8\x87V?\x8e\x11S?PCP?\xcc\x06O?\xf1RN?a\x07M?\x83DK?\xa9hH?\x94\nE?\x9d.B?mb??\xf9\x05=?\xf5X;?\xeb|:?M\xc7:?Qg;?\xbd\x0c<?\x8c\x05=?\x85I>?v\xd2??/`B?\xfe\xafF?\xafFL?b3S?,\x8dZ?\xc1}`?\x16Le?\xef\xb2h?@#j?a\x02k?\xb3\xcck?D\xd2l?\xec\xaen?\x19\xccp?\x9e\xdfr?\x82Uu?\x81\x03x?tCz?\xa5E{?\xec\xecz?5\xcey?\x08\x82x?\x83\xd2v?\xec\xb3t?\x8f\x04r?\xce\x08n?\x8d3h?\x11@a?\x1e\xfbX?\x9b\x11P?\xfc}G?\x08\'

...

Я использовал пакеты wave и soundfile для создания wav-файла, но он никогда не соответствует исходному формату. Я мог экспортировать файл из оригинального программного обеспечения, так что это должно работать.

import wave


    wav = wave.open(wavfile, 'rb')
    print("filename :", wavfile)
    print("channels :", wav.getnchannels())
    print("sampwidth:", wav.getsampwidth())
    print("framerate:", wav.getframerate())
    print("nframes  :", wav.getnframes())

Результат:

filename : c:\DATEN\TS_org.wav
channels : 1
sampwidth: 2
framerate: 32768
nframes  : 16384

Я установил эти параметры для нового файла и добавил BLOB:

def create_audiofile(blobin, saveto):
    nchannels = 1
    #ok to read in another analyser, but wrong sound sampwidth = 1
    sampwidth = 2
    framerate = 32768
    nframes = 16384

    audio = wave.open (saveto, 'wb')
    audio.setnchannels (nchannels)
    audio.setsampwidth (sampwidth)
    audio.setframerate (framerate)
    audio.setnframes (nframes)
    audio.writeframes(blobin)

    #also no success
    #audio.writeframesraw(blobin)

Я проверил несколько веб-сайтов и ответил здесь, в SO. Существует хорошее описание здесь, но у меня никогда не было рабочего wav-файла.

Первые 36 байт исходного файла выглядят так:

Bytenr :0       1       2       3       4       5       6       7       8       9       10      11      12      13      14      15      16      17      18      19      20      21      22      23      24      25      26      27      28      29      30      31      32      33      34      35      
integer:82      73      70      70      36      128     0       0       87      65      86      69      102     109     116     32      16      0       0       0       1       0       1       0       0       128     0       0       0       0       1       0       2       0       16      0       
hexcode:0x52    0x49    0x46    0x46    0x24    0x80    0x0 0x0 0x57    0x41    0x56    0x45    0x66    0x6d    0x74    0x20    0x10    0x0 0x0 0x0 0x1 0x0 0x1 0x0 0x0 0x80    0x0 0x0 0x0 0x0 0x1 0x0 0x2 0x0 0x10    0x0 
ASCII  :R       I       F       F       $                               W       A       V       E       f       m       t               #                               #               #                                                               #               #               #               

Как я могу использовать эту информацию для создания нового файла wav?

Изменить

Это забавный скрипт от @mivk как скрипт на Python для проверки конверсии:

import subprocess
infile =("e:\\data\\wav\\raw.pcm")
ffmpeg = "e:\\data\\wav\\ffmpeg.exe"
samples = [8000, 11025, 22050, 16000, 32000, 22050, 44100]
formats = ['alaw', 'f32be', 'f32le', 'f64be', 'f64le', 'mulaw', 's16be', 's16le', 's24be', 's24le', 's32be',
              's32le', 's8', 'u16be', 'u16le', 'u24be', 'u24le', 'u32be', 'u32le', 'u8']
for ar in samples:
    for f in formats:
        outfile = infile[:-4] + "_%s_%s.wav"%(f, ar)
        order = '%s -f %s -ar %d -ac 1 -i %s %s'%(ffmpeg, f, ar, infile, outfile)
        subprocess.call(order)


person Papageno    schedule 09.02.2020    source источник
comment
Ваш BLOB в базе данных начинается с RIFF....WAVE или нет? Если это так, это уже данные wav, и вы можете сохранить их в файл как есть. Если это не так, и RIFF... в вашем вопросе исходит из сгенерированного вами файла, то ваши исходные данные являются необработанными PCM. В этом случае вам необходимо выяснить точные данные об этих данных PCM (16, 24 или другие биты на выборку; 44,1, 48 или другая частота дискретизации МГц и т. д.). Я думаю, что проще всего, если вам нужно угадать эту информацию, это передать необработанные данные PCM в ffmpeg с различными параметрами, пока он не выдаст правильный файл .wav.   -  person mivk    schedule 09.02.2020
comment
BLOB не начинается с RIFF. Упомянутые первые 36 байт взяты из файла, как и должно быть. У меня есть код VB, но я не уверен, что он правильный, потому что я не могу его проверить. Единственное, что у меня есть, это 16 бит и 32768 выборок/с.   -  person Papageno    schedule 09.02.2020
comment
См. этот ответ для примеров вариантов, которые можно попробовать с ffmpeg, чтобы найти правильную информацию PCM. Вам необходимо предоставить эту информацию, чтобы необработанный PCM можно было поместить в правильный контейнер .wav. Если вы можете опубликовать ссылку на один такой блок PCM, мы могли бы попытаться найти правильную информацию.   -  person mivk    schedule 09.02.2020
comment
Хорошо, я проверил файлы с помощью ffprobe и изменил параметры с помощью ffmpeg на: Поток #0:0: Аудио: pcm_s16le ([1][0][0][0] / 0x0001), 32768 Гц, 1 канал, s16, 524 кбит/с (это исходный файл), но я все равно получаю только белый шум. Итак, моим следующим испытанием будет BLOB. Возможно, мне нужно изменить формат. Тем не менее, спасибо.   -  person Papageno    schedule 09.02.2020
comment
Вот забавная команда для создания различных wav-файлов из файла raw.pcm: for ar in 8000 11025 22050 16000 32000 22050 44100; do for f in alaw f32be f32le f64be f64le mulaw s16be s16le s24be s24le s32be s32le s8 u16be u16le u24be u24le u32be u32le u8; do ffmpeg -f $f -ar $ar -ac 1 -i raw.pcm test-$f-$ar-ac1.wav; done; done . У одного из них должен быть хороший шанс звучать правильно...   -  person mivk    schedule 09.02.2020
comment
Действительно смешно. К сожалению, не повезло.   -  person Papageno    schedule 10.02.2020
comment
Вы уверены, что байты, которые вы извлекаете, верны? В вашем примере с 224 байтами большинство байтов появляются от 1 до 3 раз, кроме ? который появляется 58 раз. Это кажется странным. Разве что-то на выходе из базы данных не заменяет некоторые байты на ?.   -  person mivk    schedule 10.02.2020
comment
Это часть временного сигнала инструмента. Сам файл выложить не смог. Тем временем я получил полный код VB и обсуждаю его с кодером. Займет время...   -  person Papageno    schedule 10.02.2020