Подтвердить что ты не робот

Захват аудио 192 кГц с использованием Python 3

Мне нужно захватить аудио 192 кГц для некоторых экспериментов по биоакустике с использованием Python 3. У меня есть аппаратное обеспечение, звуковая карта Sound Devices USBPre 2, микрофон с хорошей частотой отклика до 100 кГц, и я включил свой os (ubuntu 13.04) для выборки с этой карты на частоте 192 кГц.

Я пробовал записывать с помощью PyAudio. Он работает, и даст мне wav файл с частотой дискретизации 192 кГц. Однако, когда я смотрю на спектры, нет мощности выше 24 кГц, что говорит о том, что PyAudio на самом деле не захватывает 192 кГц, а скорее на частоте 48 кГц. Однако, когда я записываю использование Audacity с вводом от JACK, я получаю хорошую запись с мощностью до 96 кГц. Итак, у меня сложилось впечатление, что PyAudio на самом деле не пробует звук на 192 кГц, хотя он должен быть способен. Как это исправить?

Я запускаю JACK без ошибок:

/usr/bin/jackd -R -dalsa -Chw:1,0 -n3 -o1 -p2048 -r192000

jackd 0.122.0
Copyright 2001-2009 Paul Davis, Stephane Letz, Jack O'Quinn, Torben Hohn and others.
jackd comes with ABSOLUTELY NO WARRANTY
This is free software, and you are welcome to redistribute it
under certain conditions; see the file COPYING for details

JACK compiled with System V SHM support.
loading driver ..
apparent rate = 192000
creating alsa driver ... -|hw:1,0|2048|3|192000|0|1|nomon|swmeter|-|32bit
control device hw:0
configuring for 192000Hz, period = 2048 frames (10.7 ms), buffer = 3 periods
ALSA: final selected sample format for capture: 24bit little-endian
ALSA: use 3 periods for capture

Инициализировать PyAudio (без каких-либо реальных ошибок (насколько я могу судить)):

p = pyaudio.PyAudio()
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
bt_audio_service_open: connect() failed: Connection refused (111)
bt_audio_service_open: connect() failed: Connection refused (111)
bt_audio_service_open: connect() failed: Connection refused (111)
bt_audio_service_open: connect() failed: Connection refused (111)
ALSA lib pcm_dmix.c:957:(snd_pcm_dmix_open) The dmix plugin supports only playback stream

Откройте поток PyAudio:

stream = p.open(format=pyaudio.paInt32,
                channels=1,rate=192000,
                input=True,
                frames_per_buffer=2048)

У меня есть изображения спектрограмм, если кто-то хочет проверить мою интерпретацию, что PyAudio не захватывает 192 кГц (но Audacity делает):

Спектрограмма звука, захваченного usig PyAudio Spectrogram of sound captured usig PyAudio

Спектрограмма звука, захваченного usig Audacity Spectrogram of sound captured usig Audacity

Как я могу записать звук с 192 000 сэмплов/с с помощью PyAudio? Также приветствуются предложения других способов захвата звука с помощью Python 3.

4b9b3361

Ответ 1

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

При попытке воспроизвести вашу проблему с PyAudio в OS X, я всегда работал в [Errno Input overflowed] -9981 (например, несколько других люди, это кажется). Кроме того, конфигурации, которые p.is_format_supported() сообщили как ОК, вызвали эти ошибки. Поэтому я взломал script, который просто пытается записать со всеми возможными перестановками настроек записи.

Этот script проверяет все перестановки списков устройств, частоты дискретизации, форматов и каналов защитным способом и сохраняет результаты в файлах, названных в соответствии с настройками записи.

import os
import pyaudio
import sys

# === These parameters will be permuted ===========
DEVICES = [0, 1, 2]
RATES = [44100, 48000, 192000]
FORMATS = ['Float32', 'Int32', 'Int24', 'Int16', 'Int8', 'UInt8']
CHANNELS = [1, 2]
# =================================================

CHUNK = 1024
COLUMNS = (('filename', 30),
           ('result', 9),
           ('dev', 5),
           ('rate', 8),
           ('format', 9),
           ('channels', 10),
           ('chunk', 7),
           ('reason', 0))
STATUS_MSG = "Recording... "

pa = pyaudio.PyAudio()


def get_format(format):
    fmt = getattr(pyaudio, 'pa%s' % format)
    return fmt


def record(filename=None,
           duration=5,
           dev=0,
           rate=44100,
           format='Float32',
           channels=2,
           chunk=1024,):
    """Record `duration` seconds of audio from the device with index `dev`.
    Store the result in a file named according to recording settings.
    """
    if filename is None:
        filename = "dev{dev}-{rate}-{format}-{channels}ch.raw".format(**locals())
    result = 'FAILURE'
    reason = ''

    outfile = open(filename, 'w')
    print STATUS_MSG,
    sys.stdout.flush()

    try:
        stream = pa.open(input_device_index=dev,
                         rate=rate,
                         format=get_format(format),
                         channels=channels,
                         frames_per_buffer=chunk,
                         input=True,
                         )

        try:
            for i in range(0, rate / (chunk) * duration):
                a = stream.read(chunk)
                outfile.write(a)
            result = 'SUCCESS'
        # Catch exceptions when trying to read from stream
        except Exception, e:
            reason = "'%s'" % e
    # Catch exceptions when trying to even open the stream
    except Exception, e:
        reason = "'%s'" % e

    outfile.close()

    # Don't leave files behind for unsuccessful attempts
    if result == 'FAILURE':
        os.remove(filename)
        filename = ''

    info = {}
    for col_name, width in COLUMNS:
        info[col_name] = str(locals()[col_name]).ljust(width)

    msg = "{filename}{result}{dev}{rate}{format}{channels}{chunk}{reason}"
    print msg.format(**info)

def main():
    # Build the header line
    header = 'STATUS'.ljust(len(STATUS_MSG) + 1)
    for col_name, width in COLUMNS:
        header += col_name.upper().ljust(width)
    print header
    print "=" * len(header)

    # Record samples for all permutations of our parameter lists
    for dev in DEVICES:
        for rate in RATES:
            for format in FORMATS:
                for channels in CHANNELS:
                    record(duration=2,
                           dev=dev,
                           rate=rate,
                           format=format,
                           channels=channels,
                           chunk=CHUNK)

if __name__ == '__main__':
    main()

Пример вывода (упрощенный):

STATUS        FILENAME                      RESULT   DEV  RATE    FORMAT   CHANNELS  CHUNK  REASON
==================================================================================================
Recording...  dev0-44100-Float32-1ch.raw    SUCCESS  0    44100   Float32  1         1024
Recording...  dev0-44100-Float32-2ch.raw    SUCCESS  0    44100   Float32  2         1024
Recording...  dev0-44100-Int16-1ch.raw      SUCCESS  0    44100   Int16    1         1024
Recording...  dev0-44100-Int16-2ch.raw      SUCCESS  0    44100   Int16    2         1024
Recording...                                FAILURE  0    192000  Float32  1         1024   '[Errno Input overflowed] -9981'
Recording...                                FAILURE  0    192000  Float32  2         1024   '[Errno Input overflowed] -9981'
Recording...                                FAILURE  0    192000  Int16    1         1024   '[Errno Input overflowed] -9981'
Recording...                                FAILURE  0    192000  Int16    2         1024   '[Errno Input overflowed] -9981'
Recording...  dev1-44100-Float32-1ch.raw    SUCCESS  1    44100   Float32  1         1024
Recording...  dev1-44100-Float32-2ch.raw    SUCCESS  1    44100   Float32  2         1024
Recording...  dev1-44100-Int16-1ch.raw      SUCCESS  1    44100   Int16    1         1024
Recording...  dev1-44100-Int16-2ch.raw      SUCCESS  1    44100   Int16    2         1024
Recording...                                FAILURE  1    192000  Float32  1         1024   '[Errno Input overflowed] -9981'
Recording...                                FAILURE  1    192000  Float32  2         1024   '[Errno Input overflowed] -9981'
Recording...                                FAILURE  1    192000  Int16    1         1024   '[Errno Input overflowed] -9981'
Recording...                                FAILURE  1    192000  Int16    2         1024   '[Errno Input overflowed] -9981'
Recording...                                FAILURE  2    44100   Float32  1         1024   '[Errno Invalid number of channels] -9998'
Recording...                                FAILURE  2    44100   Float32  2         1024   '[Errno Invalid number of channels] -9998'
Recording...                                FAILURE  2    44100   Int16    1         1024   '[Errno Invalid number of channels] -9998'
Recording...                                FAILURE  2    44100   Int16    2         1024   '[Errno Invalid number of channels] -9998'
Recording...                                FAILURE  2    192000  Float32  1         1024   '[Errno Invalid number of channels] -9998'
Recording...                                FAILURE  2    192000  Float32  2         1024   '[Errno Invalid number of channels] -9998'
Recording...                                FAILURE  2    192000  Int16    1         1024   '[Errno Invalid number of channels] -9998'
Recording...                                FAILURE  2    192000  Int16    2         1024   '[Errno Invalid number of channels] -9998'