Thread: SoundManagerAlsa.cpp and multi-threaded applications

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Nov 2014
    Posts
    26

    SoundManagerAlsa.cpp and multi-threaded applications

    I am trying to understand a few things about this SoundManagerAlsa script and multi-threading.

    Here is how the SoundManagerAlsa script is being called:

    Code:
    {
      SoundManager::SoundManager soundManager(portNumber);
      soundManager.openSoundDevice();
      soundManager.startServer();
    
      cmdQueue.get(); // blocks until a command is available in the queue
    
      soundManager.shutDown();
      }
    So from the top here's openSoundDevice():

    Code:
    void SoundManager::openSoundDevice()
      {
        initiateSoundDevice(); // Close then reopen the device.
      }
    now initiateSoundDevice():

    Code:
    void SoundManager::initiateSoundDevice()
      {
        using namespace TimeStuff;
    
        if (!m_toneDev || m_audioSetup.threadIsRunning) // If the thread is already running then shut it down and reopen the audio device.
        {
          printf("%10.3f Shut down thread.\n", fToHMS(now()));
          shutDown();
    
          assert(!m_audioSetup.threadIsRunning);
          if (m_audioSetup.threadIsRunning)
          {
            perror("Unable to shut down audio update thread");
          }
          else
          {
            printf("%10.3f Open sound device.\n", fToHMS(now()));
    
            for (int i=0 ; audioDeviceName[i] && !m_toneDev ; i++)
            {
              int result = snd_pcm_open(&m_toneDev, audioDeviceName[i], SND_PCM_STREAM_PLAYBACK, 0);
              if (result < 0)
              {
                std::cerr << "Unable to open sound device(" << audioDeviceName[i] << "), tone canceled. Errmsg: " << snd_strerror(result) << std::endl;
                m_toneDev = NULL;
              }
              else
              {
                printf("%10.3f Sound device (%s) open. Handle: %p\n", fToHMS(now()), audioDeviceName[i], m_toneDev);
              }
            }
          }
        }
    
        if (m_toneDev && !m_audioSetup.threadIsRunning) // Audio device is currently open.
        {
          m_audioSetup.clear();
          /**
           * We only want 2 periods in the ring buffer.
           * This is enough to allow uninterrupted playback, and it allows us to interrupt ongoing tones reasonably fast.
           *
           * We can have two periods in the buffer, and a third waiting to get access to the buffer.
           * This means that if we want to interrupt an ongoing tone, the reaction time will be between two and three periods.
           *
           * With
           *   sampleRate = 44100 samples per second
           *      2 periods
           *   1024 samples pr period
           * we get:
           * timePerPeriod = nSamplesPerPeriod / sampleRate = 1024 / 44100 = 23.2ms
           *
           * This means that this thread will run once per 23,2ms when a tone is being played.
           * And if the tone must be interrupted the response time is in the range [2*23.2 - 3*23.2] = [46.4 - 69.6]ms.
           */
          snd_pcm_hw_params_t *hwparams;
          snd_pcm_sw_params_t *swparams;
          snd_pcm_hw_params_alloca(&hwparams); // Allocation (alloca) is deleted when function exits.
          snd_pcm_sw_params_alloca(&swparams);
    
          // Get all parameters:
          if (m_toneDev) handleSetupError(snd_pcm_hw_params_any(                 m_toneDev, hwparams                                ), "Unable to read hardware parameters for sound device.");
          if (m_toneDev) handleSetupError(snd_pcm_hw_params_set_rate_resample(   m_toneDev, hwparams, 1                             ), "Unable to set re-sampling for sound device.");
          if (m_toneDev) handleSetupError(snd_pcm_hw_params_set_access(          m_toneDev, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED ), "Unable to set interleaved format for sound device.");
          if (m_toneDev) handleSetupError(snd_pcm_hw_params_set_format(          m_toneDev, hwparams, SND_PCM_FORMAT_S16_LE         ), "Unable to set sample format for sound device.");
          if (m_toneDev) handleSetupError(snd_pcm_hw_params_set_channels(        m_toneDev, hwparams, m_audioSetup.nChannels        ), "Unable to set number of channels for sound device.");
          if (m_toneDev) handleSetupError(snd_pcm_hw_params_set_rate_near(       m_toneDev, hwparams, &m_audioSetup.sampleRate, NULL), "Unable to set sample rate for sound device.");
          if (m_toneDev) handleSetupError(snd_pcm_hw_params_set_buffer_size_near(m_toneDev, hwparams, &m_audioSetup.bufferSize      ), "Unable to set buffer size for sound device.");
          if (m_toneDev) handleSetupError(snd_pcm_hw_params_set_period_size_near(m_toneDev, hwparams, &m_audioSetup.periodSize, NULL), "Unable to set period size for sound device.");
          if (m_toneDev) handleSetupError(snd_pcm_hw_params(                     m_toneDev, hwparams                                ), "Unable to write hw parameters to sound device.");
    
          if (m_toneDev)
          {
            m_audioSetup.msPerSample = 1000.0 / static_cast<double>(m_audioSetup.sampleRate);
            printf("%10.3f Sound device Hardware setup:\n", fToHMS(now()));
            printf("          Millisec per sample: %fms\n", m_audioSetup.msPerSample);
            printf("          Millisec per period: %fms\n", m_audioSetup.msPerSample * static_cast<double>(m_audioSetup.periodSize));
            printf("             Samples per period: %u\n", static_cast<unsigned>(m_audioSetup.periodSize));
            printf("             Samples per buffer: %u\n", static_cast<unsigned>(m_audioSetup.bufferSize));
    
            m_audioSetup.audioBuffer = new int16_t[m_audioSetup.periodSize * m_audioSetup.nChannels];
            assert(m_audioSetup.audioBuffer);
    
            if (!m_audioSetup.audioBuffer)
            {
              std::cerr << "Unable to allocate audio buffer. Tone cancelled." << std::endl;
              snd_pcm_close(m_toneDev);
              m_toneDev = NULL;
            }
          }
    
          if (m_toneDev)
          {
            m_audioSetup.threadIsRunning = true;
            m_toneThread = threadfunc::ThreadCreate( 6, threadUpdateTone, this );
          }
        }
      }
    The portion that confuses me is:

    Code:
    if (!m_toneDev || m_audioSetup.threadIsRunning) // If the thread is already running then shut it down and reopen the audio device.
        {
          printf("%10.3f Shut down thread.\n", fToHMS(now()));
          shutDown();
    
          assert(!m_audioSetup.threadIsRunning);
          if (m_audioSetup.threadIsRunning)
          {
            perror("Unable to shut down audio update thread");
          }
          else
          {
            printf("%10.3f Open sound device.\n", fToHMS(now()));
    
            for (int i=0 ; audioDeviceName[i] && !m_toneDev ; i++)
            {
              int result = snd_pcm_open(&m_toneDev, audioDeviceName[i], SND_PCM_STREAM_PLAYBACK, 0);
              if (result < 0)
              {
                std::cerr << "Unable to open sound device(" << audioDeviceName[i] << "), tone canceled. Errmsg: " << snd_strerror(result) << std::endl;
                m_toneDev = NULL;
              }
              else
              {
                printf("%10.3f Sound device (%s) open. Handle: %p\n", fToHMS(now()), audioDeviceName[i], m_toneDev);
              }
            }
          }
        }
    What is going on here? Why would you have a multi-threaded audio device? You only have one speaker, you can't play two tones at once, so whats the point? I mean it even stops the currently running thread from running whenever initiateSoundDevice() is called doesn't it? Why would this be a threaded application?
    Last edited by Robert Murch; 02-07-2019 at 01:44 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Multi-threaded mayhem
    By IceDane in forum C Programming
    Replies: 8
    Last Post: 03-24-2008, 08:44 AM
  2. Going from single-threaded to multi-threaded
    By Dino in forum C Programming
    Replies: 11
    Last Post: 03-23-2008, 01:14 PM
  3. gdb problem in multi-threaded app
    By IfYouSaySo in forum Linux Programming
    Replies: 1
    Last Post: 10-12-2006, 08:22 PM
  4. multi-threaded programming
    By Hermitsky in forum C++ Programming
    Replies: 29
    Last Post: 11-28-2004, 01:23 PM
  5. Multi-Threaded Sockets
    By XSquared in forum Networking/Device Communication
    Replies: 9
    Last Post: 08-28-2003, 09:54 PM

Tags for this Thread