thestk / rtaudio

A set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound, ASIO, and WASAPI) operating systems.
Other
1.49k stars 318 forks source link

RtApiPulse::callbackEvent: audio read error, Entity killed. How to find it's cause? #331

Closed mahaju closed 2 years ago

mahaju commented 2 years ago

I am using RtAudio Version 5.1.0 downloaded from http://www.music.mcgill.ca/~gary/rtaudio/release/rtaudio-5.1.0.tar.gz I built it using the configure configure options:

./configure --with-alsa --with-pulse --enable-debug

I have connected USB sound card to a hub, connected to the raspberry pi zero W. Besides this sound card this hub has a keyboard and iptime wifi antenna attached. I am using a modified version of the Duplex sample program to send 1 channel mic data form the soundcard to 2 channel headphones. After running this program continuously for almost 4 hours, the audio suddenly stopped and I started getting RtApiPulse::callbackEvent: audio read error, Entity killed. continuously.

I have also noticed that the audio latency, that is, the duration between sound going into the mic and coming out the receiver, was very short in the beginning (less than half a second), which slowly increased as time went on. After around 3 and a half hours this latency was several seconds before the finally stopped, and I started getting the error message above.

What is the cause for this? Is this a bug in the library or am I using it wrong?

Here are all the details:

result of audioprobe:

$./audioprobe

RtAudio Version 5.1.0

Compiled APIs:
  Linux PulseAudio
  Linux ALSA

Current API: Linux PulseAudio

Found 1 device(s) ...

Device Name = PulseAudio
Device ID = 0
Probe Status = Successful
Output Channels = 2
Input Channels = 2
Duplex Channels = 2
This is the default output device.
This is the default input device.
Natively supported data formats:
  16-bit int
  32-bit int
  32-bit float
Supported sample rates = 8000 16000 22050 32000 44100 48000 96000

Duplex sample program output (before error)

./Duplex 1 2 48000 0 0

Stream latency = 0 frames

Running ... press <enter> to quit (buffer frames = 960).

CMakeLists.txt :

cmake_minimum_required(VERSION 2.8)
project(Duplex)
message(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(Duplex 
           duplex.cpp
           RtAudio.cpp
)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -D__LINUX_PULSE__")
target_link_libraries(Duplex pthread pulse-simple pulse)

Duplex.cpp


#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>

typedef signed short MY_TYPE;
#define FORMAT RTAUDIO_SINT16

void usage( void ) {
  // Error function in case of incorrect command-line
  // argument specifications
  std::cout << "\nuseage: duplex Ni No fs <iDevice> <oDevice> <iChannelOffset> <oChannelOffset>\n";
  std::cout << "    where Ni = number of input channels,\n";
  std::cout << "    where No = number of output channels,\n";
  std::cout << "    fs = the sample rate,\n";
  std::cout << "    iDevice = optional input device to use (default = 0),\n";
  std::cout << "    oDevice = optional output device to use (default = 0),\n";
  std::cout << "    iChannelOffset = an optional input channel offset (default = 0),\n";
  std::cout << "    and oChannelOffset = optional output channel offset (default = 0).\n\n";
  exit( 0 );
}

int inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
           double /*streamTime*/, RtAudioStreamStatus status, void *data )
{
  // Since the number of input and output channels is equal, we can do
  // a simple buffer copy operation here.
  if ( status ) std::cout << "Stream over/underflow detected." << std::endl;

  MY_TYPE *outputBuffer_mt = (MY_TYPE *)outputBuffer;
  MY_TYPE *inputBuffer_mt = (MY_TYPE *)inputBuffer;
  int j = 0;
  for(unsigned int i = 0; i<nBufferFrames; i++){
      outputBuffer_mt[j++] = inputBuffer_mt[i];
      outputBuffer_mt[j++] = inputBuffer_mt[i];
  }

  return 0;
}

int main( int argc, char *argv[] )
{
  unsigned int channels_i, channels_o, fs, bufferBytes, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0;

  // Minimal command-line checking
  if (argc < 4 || argc > 8 ) usage();

  RtAudio adac;
  if ( adac.getDeviceCount() < 1 ) {
    std::cout << "\nNo audio devices found!\n";
    exit( 1 );
  }

  channels_i = (unsigned int) atoi(argv[1]);
  channels_o = (unsigned int) atoi(argv[2]);
  fs = (unsigned int) atoi(argv[3]);
  if ( argc > 4 )
    iDevice = (unsigned int) atoi(argv[4]);
  if ( argc > 5 )
    oDevice = (unsigned int) atoi(argv[5]);
  if ( argc > 6 )
    iOffset = (unsigned int) atoi(argv[6]);
  if ( argc > 7 )
    oOffset = (unsigned int) atoi(argv[7]);

  // Let RtAudio print messages to stderr.
  adac.showWarnings( true );

  // this many samples from input (1 channel) is copied to output (2 channels)
  unsigned int bufferFrames = 960;
  RtAudio::StreamParameters iParams, oParams;
  iParams.deviceId = iDevice;
  iParams.nChannels = channels_i;
  iParams.firstChannel = iOffset;
  oParams.deviceId = oDevice;
  oParams.nChannels = channels_o;
  oParams.firstChannel = oOffset;

  if ( iDevice == 0 )
    iParams.deviceId = adac.getDefaultInputDevice();
  if ( oDevice == 0 )
    oParams.deviceId = adac.getDefaultOutputDevice();

  RtAudio::StreamOptions options;
  //options.flags |= RTAUDIO_NONINTERLEAVED;

  bufferBytes = bufferFrames * channels_i * sizeof( MY_TYPE );
  try {
    adac.openStream( &oParams, &iParams, FORMAT, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options );
  }
  catch ( RtAudioError& e ) {
    std::cout << '\n' << e.getMessage() << '\n' << std::endl;
    exit( 1 );
  }

  // Test RtAudio functionality for reporting latency.
  std::cout << "\nStream latency = " << adac.getStreamLatency() << " frames" << std::endl;

  try {
    adac.startStream();

    char input;
    std::cout << "\nRunning ... press <enter> to quit (buffer frames = " << bufferFrames << ").\n";
    std::cin.get(input);

    // Stop the stream.
    adac.stopStream();
  }
  catch ( RtAudioError& e ) {
    std::cout << '\n' << e.getMessage() << '\n' << std::endl;
    goto cleanup;
  }

 cleanup:
  if ( adac.isStreamOpen() ) adac.closeStream();

  return 0;
}

I feel this is related to a previous issue I have raised here: https://github.com/thestk/rtaudio/issues/330

radarsat1 commented 2 years ago

There could be a memory leak. Are you able to tell somehow? (E.g. monitor the process' memory consumption over time, or run valgrind, maybe it can detect something.) Also, try comparing the pulse and ALSA backends if you can.

garyscavone commented 2 years ago

This seems stale ... I'm closing it.