使用Python3捕捉192 kHz音频

2024-03-29 12:13:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要用python3捕捉192千赫的音频用于一些生物声学实验。 我有硬件,一个usbpre2声卡,一个频率响应曲线高达100khz的麦克风,我已经启用了我的操作系统(ubuntu13.04)从这张卡上以192千赫的频率采样。在

我试过用PyAudio录音。它似乎可以工作,并将给我一个采样率为192千赫的wav文件。然而,当我看频谱时,没有超过24千赫的功率,这表明PyAudio并没有真正捕捉到192千赫,而是在48千赫。然而,当我用Audacity和杰克的输入录音时,我得到了一个高达96kHz的不错的录音。所以,我觉得PyAudio并没有在192千赫的频率下对声音进行采样,尽管它应该可以。 怎么解决这个问题?在

我启动杰克时没有出错:

/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(没有任何实际错误(据我所知)):

^{pr2}$

打开PyAudio流:

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

我有光谱图的图像,以防有人想验证我的解释,PyAudio无法捕捉到192 kHz(但Audacity可以):

使用PyAudio捕获的声音频谱图Spectrogram of sound captured usig PyAudio

使用Audacity拍摄的声音频谱图Spectrogram of sound captured usig Audacity

如何使用PyAudio以192000个采样/秒的速度录制声音? 对于使用python3捕捉声音的其他方法的建议也很受欢迎。在


Tags: and声音forframesratedriverwithpython3
1条回答
网友
1楼 · 发布于 2024-03-29 12:13:56

这并不意味着是一个决定性的答案,而是一种尝试,帮助你也许可以找到问题自己。在

在OSX上尝试用PyAudio重现您的问题时,我总是遇到[Errno Input overflowed] -9981(就像several其他{a2},它是seems)。 另外,p.is_format_supported()报告为正常的配置也会导致这些错误。所以我创建了一个脚本,它试图记录所有可能的录制设置的排列。在

此脚本以防御方式探测设备采样率格式频道的列表的所有排列,并将结果保存到根据录制设置命名的文件中。在

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()

样本输出(简化):

^{pr2}$

相关问题 更多 >