Skip to content Skip to sidebar Skip to footer

Reading Qaudioprobe Buffer

The Qt documentation (https://doc.qt.io/qtforpython-5/PySide2/QtMultimedia/QAudioBuffer.html) says that we should read the buffer from QAudioProbe like this: // With a 16bit sample

Solution 1:

I ran into the same issue with a fresh PySide2 5.13.2 environment, and running print(probe.data().toBytes()) returned chunks of size 0 which I knew couldn't be the case because other built-in functionality was accessing the data.

I hate this hack as much as anyone else, but if you want to test things it is possible to access the buffer contents this way (please do not use this in production code):

  1. Find out about the datatype, endian-ness etc of your buffer via format, and infer the proper C type that you'll need (e.g. signed int 16).

  2. Extract the printed address from the VoidPtr printout, and convert it to an integer

  3. Create a numpy array by reading at the given address, with the given type, and by the given amount of frames.


Code:

First of all, somewhere in your app, you'll be connecting your QAudioProbe to your source via setSource, and then the audioBufferProbed signal to a method e.g.:

self.audio_probe.audioBufferProbed.connect(self.on_audio_probed)

Then, the following on_audio_probed functionality will fetch the numpy array and print its norm, which should increase in presence of sound:

import numpy as np
import ctypes

defget_buffer_info(buf):
    """
    """
    num_bytes = buf.byteCount()
    num_frames = buf.frameCount()
    #
    fmt = buf.format()
    sample_type = fmt.sampleType()  # float, int, uint
    bytes_per_frame = fmt.bytesPerFrame()
    sample_rate = fmt.sampleRate()
    #if sample_type == fmt.Float and bytes_per_frame == 4:
        dtype = np.float32
        ctype = ctypes.c_float
    elif sample_type == fmt.SignedInt and bytes_per_frame == 2:
        dtype = np.int16
        ctype = ctypes.c_int16
    elif sample_type == fmt.UnsignedInt and bytes_per_frame == 2:
        dtype = np.uint16
        ctype = ctypes.c_uint16
    #return dtype, ctype, num_bytes, num_frames, bytes_per_frame, sample_rate

defon_audio_probed(audio_buffer):
    """
    """
    cdata = audio_buffer.constData()
    (dtype, ctype, num_bytes, num_frames,
     bytes_per_frame, sample_rate) = get_buffer_info(audio_buffer)
    pointer_addr_str = str(cdata).split("Address ")[1].split(", Size")[0]
    pointer_addr = int(pointer_addr_str, 16)
    arr = np.array((ctype * num_frames).from_address(pointer_addr))
    print(np.linalg.norm(arr))  # should increase in presence of sound

I just tested it with a QAudioRecorder using 16-bit unsigned wavs, and it worked "fine" (audio looked and sounded good, see screenshot below). Again, this is basically a meme code so anything above showing your fancy audio buffered app to your cousins will be extremely risky, do not use in serious code. But in any case let me know if any other workarounds worked for you, or if this also worked in a different context! Hopefully if the devs see that people are actually using this approach they'll fix the issue much sooner :)

enter image description here

Cheers! Andres

Post a Comment for "Reading Qaudioprobe Buffer"