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.51k stars 322 forks source link

Audio passthrough becomes distorted after long use in raspberry pi zero #330

Closed mahaju closed 2 years ago

mahaju commented 3 years ago

I am using RtAudio library to send 1 channel mic data to 2 channel speaker in a USB sound card connected to raspberry pi zero

I use 48000 kHz sampling frequency and buffer size 512, modified in the Duplex sample program

This problem is seen in other sampling frequencies and buffer sizes as well

The program sends mic audio to left and right channels of the speaker normally for a while but after letting the program run for a few minutes (5-10 minutes) the output starts getting distorted

If I stop the program and start it again, it is normal in the beginning but starts getting distorted again after a while

However, the problem is sometimes this distortion does not happen, and the audio can play normally for more than 30 minutes

I built RtAudio using --with-alsa option. What can I do to find out the cause of this issue?

garyscavone commented 3 years ago

Perhaps the program sometimes starts experiencing under/over-runs? Are you checking the ‘status’ flag? A larger buffer size might help. Does it happen with the default duplex.cpp program (before your modification)?

On Oct 25, 2021, at 5:10 AM, mahaju @.***> wrote:

I am using RtAudio library to send 1 channel mic data to 2 channel speaker in a USB sound card connected to raspberry pi zero

I use 48000 kHz sampling frequency and buffer size 512, modified in the Duplex sample program

This problem is seen in other sampling frequencies and buffer sizes as well

The program sends mic audio to left and right channels of the speaker normally for a while but after letting the program run for a few minutes (5-10 minutes) the output starts getting distorted

If I stop the program and start it again, it is normal in the beginning but starts getting distorted again after a while

However, the problem is sometimes this distortion does not happen, and the audio can play normally for more than 30 minutes

I built RtAudio using --with-alsa option. What can I do to find out the cause of this issue?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

mahaju commented 3 years ago

This is the exact code that I am using:

#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 built the RtAduio library using this method:

  1. Download and extract rtaudio-5.1.0.tar.gz (that is, not download from github) using tar -xzf rtaudio-x.x.tar.gz
  2. build using this method
    
    ./configure --with-alsa
    make
3. install using `sudo checkinstall`

Once I have the library I build it using cmake. This is the CMakeLists.txt file:

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_ALSA__") target_link_libraries(Duplex asound pthread)


Inside the inout() callback function I have not removed the 
` if ( status ) std::cout << "Stream over/underflow detected." << std::endl;`
which was part of the original program. I use 1 channel mic audio as input and copy it to 2 channel output of the soundcard using a method suggested in a previous question of mine. I use 48000Hz sampling frequency. When the audio distortion happens I do not see the "Stream over/underflow detected." message, so I think 'status' does not change at this point.
garyscavone commented 2 years ago

Closing due to inactivity.