예제 #1
0
/*
 * Close out audio sync - stop and disconnect from SDL
 */
CSDLAudioSync::~CSDLAudioSync (void)
{
  Our_SDL_PauseAudio(1);
  Our_SDL_CloseAudio();
  for (int ix = 0; ix < DECODE_BUFFERS_MAX; ix++) {
    if (m_sample_buffer[ix] != NULL)
      free(m_sample_buffer[ix]);
    m_sample_buffer[ix] = NULL;
  }
  audio_message(LOG_NOTICE, 
		"Audio sync skipped %u buffers", 
		m_skipped_buffers);
  audio_message(LOG_NOTICE, "didn't fill %u buffers", m_didnt_fill_buffers);
  SDL_DestroySemaphore(m_audio_waiting);
}
예제 #2
0
/*
 * Create an CPortAudioSync for a session.  Don't alloc any buffers until
 * config is called by codec
 */
CPortAudioSync::CPortAudioSync (CPlayerSession *psptr, int volume) :
    CBufferAudioSync(psptr, volume)
{
    PaError err;
    err = Pa_Initialize();
    if (err != paNoError) {
        audio_message(LOG_CRIT, "resp from Pa_Initialize is %d %s", err,
                      Pa_GetErrorText(err));
    }

    m_volume = volume;
    m_pa_stream = NULL;
}
예제 #3
0
int do_we_have_audio (void)
{
    PaError err;
    err = Pa_Initialize();

    if (err != paNoError) {
        audio_message(LOG_ERR, "No audio - %d %s", err,
                      Pa_GetErrorText(err));
        return 0;
    }

    Pa_Terminate();
    return (1);
}
예제 #4
0
/*
 * codec api - set up information about the stream
 */
void CSDLAudioSync::set_config (int freq, 
			     int channels, 
			     audio_format_t format, 
			     uint32_t sample_size) 
{
  if (m_config_set != 0) 
    return 0;
  
  audio_message(LOG_DEBUG, "configure audio freq %d chan %d format %d",
			freq, channels, format);
  switch (format) {
  case AUDIO_FMT_U8:
  case AUDIO_FMT_S8:
  case AUDIO_FMT_HW_AC3:
    m_bytes_per_sample_input = sizeof(uint8_t);
    m_bytes_per_sample_output = sizeof(uint8_t);
    break;
  case AUDIO_FMT_FLOAT:
    // we convert float to S16 (native format)
    m_bytes_per_sample_input = sizeof(float);
    m_bytes_per_sample_output = sizeof(int16_t);
    break;
  default:
    m_bytes_per_sample_input = sizeof(int16_t);
    m_bytes_per_sample_output = sizeof(int16_t);
    break;
  }

  if (sample_size == 0) {
    int temp;
    temp = freq;
    while ((temp & 0x1) == 0) temp >>= 1;
    sample_size = temp;
    while (sample_size < 1024) sample_size *= 2;
    while (((sample_size * 1000) % freq) != 0) sample_size *= 2;
  } 
예제 #5
0
// Sync task api - initialize the sucker.
// May need to check out non-standard frequencies, see about conversion.
// returns 1 for initialized, -1 for error
int CPortAudioSync::InitializeHardware (void)
{
    uint32_t bytes_per_sample;
    uint32_t sample_size;
    bool need_convert = false;

    // bytes per sample is the # of bytes for the output buffer
    bytes_per_sample = 2;
    if (m_decode_format == AUDIO_FMT_U8 || m_decode_format == AUDIO_FMT_S8)
        bytes_per_sample = 1;

    sample_size = m_samples_per_frame;
    uint32_t ix;
    for (ix = 2; ix <= 0x8000; ix <<= 1) {
        if ((sample_size & ~(ix - 1)) == 0) {
            break;
        }
    }

    audio_message(LOG_DEBUG, "Sample size is %d %d", ix, m_samples_per_frame);
    sample_size = ix;
#if 0
    if (m_output_buffer_size_bytes < 4096)
        m_output_buffer_size_bytes = 4096;
#endif
    if (config.get_config_value(CONFIG_LIMIT_AUDIO_SDL_BUFFER) > 0 &&
            sample_size > 4096)
        sample_size = 4096;

    while (sample_size * m_bytes_per_sample_input > m_sample_buffer_size / 4) {
        sample_size /= 2;
    }

    PaSampleFormat format;
    double freq = (double) m_freq;
    format = fmt_to_pa_format[m_decode_format];
    if (format == 0) {
        format = paInt16;
        need_convert = true;
    }
    PaError err;
    err = Pa_OpenDefaultStream(&m_pa_stream,
                               0,
                               m_channels,
                               format,
                               freq,
                               sample_size,
                               0,
                               c_audio_callback,
                               this);

    m_got_channels = m_channels;
    if (err != paNoError) {
        if (err == paInvalidChannelCount) {
            format = paInt16;
            err = Pa_OpenDefaultStream(&m_pa_stream,
                                       0,
                                       2,
                                       format,
                                       freq,
                                       sample_size,
                                       0,
                                       c_audio_callback,
                                       this);
            m_got_channels = 2;
            need_convert = true;
        }
        if (err != paNoError) {
            audio_message(LOG_CRIT, "Couldn't open audio, %s",
                          Pa_GetErrorText(err));
            return (-1);
        }
    }

    audio_message(LOG_DEBUG, "freq %u chans %u samples %u",
                  m_freq, m_got_channels, sample_size);
    m_output_buffer_size_bytes = sample_size * m_bytes_per_sample_input;
    if (m_decode_format == AUDIO_FMT_FLOAT || need_convert) {
        m_bytes_per_sample_output = sizeof(int16_t) * m_got_channels;
        audio_message(LOG_DEBUG, "convert buffer size is %d", m_output_buffer_size_bytes);
        audio_convert_init(m_output_buffer_size_bytes, sample_size);
    } else {
        m_bytes_per_sample_output = m_got_channels * bytes_per_sample;
    }

    return 1;
}
예제 #6
0
// Sync task api - initialize the sucker.
// May need to check out non-standard frequencies, see about conversion.
// returns 1 for initialized, -1 for error
int CSDLAudioSync::InitializeHardware (void) 
{
  uint32_t bytes_per_sample;
  SDL_AudioSpec wanted;
  
  memset(&wanted, 0, sizeof(wanted));
  wanted.freq = m_freq;
  wanted.channels = m_channels;
  // bytes per sample is the # of bytes for the output buffer
  bytes_per_sample = 2;
  switch (m_decode_format) {
  case AUDIO_FMT_U8: wanted.format = AUDIO_U8; bytes_per_sample = 1; break;
  case AUDIO_FMT_S8: wanted.format = AUDIO_S8; bytes_per_sample = 1; break;
  case AUDIO_FMT_U16LSB: wanted.format = AUDIO_U16LSB; break;
  case AUDIO_FMT_U16MSB: wanted.format = AUDIO_U16MSB; break;
  case AUDIO_FMT_S16LSB: wanted.format = AUDIO_S16LSB; break;
  case AUDIO_FMT_S16MSB: wanted.format = AUDIO_S16MSB; break;
  case AUDIO_FMT_U16: wanted.format = AUDIO_U16SYS; break;
  case AUDIO_FMT_S16: wanted.format = AUDIO_S16SYS; break;
  case AUDIO_FMT_FLOAT: wanted.format = AUDIO_S16SYS; break;
  case AUDIO_FMT_HW_AC3: 
    wanted.format = AUDIO_FORMAT_HW_AC3; 
    bytes_per_sample = 1;
    break;
  }

  uint32_t sample_size;
  sample_size = m_samples_per_frame * m_channels;
#ifndef _WIN32
  uint32_t ix;
  for (ix = 2; ix <= 0x8000; ix <<= 1) {
    if ((sample_size & ~(ix - 1)) == 0) {
      break;
    }
  }
  ix >>= 1;
  audio_message(LOG_DEBUG, "Sample size is %d", ix);
  sample_size = ix;
#else
  sample_size = 4096;
#endif
#if 0
  if (m_output_buffer_size_bytes < 4096)
    m_output_buffer_size_bytes = 4096;
#endif
  if (config.get_config_value(CONFIG_LIMIT_AUDIO_SDL_BUFFER) > 0 &&
      sample_size > 4096) 
    sample_size = 4096;
  if (sample_size < m_freq / 10) 
    sample_size = 4096;

  while (sample_size * m_bytes_per_sample_input > m_sample_buffer_size / 4) {
    sample_size /= 2;
  }
  wanted.samples = sample_size;
  wanted.callback = c_audio_callback;
  wanted.userdata = this;
#if 1
  audio_message(LOG_INFO, 
		"requested f %d chan %d format %x samples %d",
		wanted.freq,
		wanted.channels,
		wanted.format,
		wanted.samples);
#endif
  int ret = Our_SDL_OpenAudio(&wanted, &m_obtained);
  if (ret < 0) {
    if (wanted.channels > 2) {
      wanted.channels = 2;
      ret = Our_SDL_OpenAudio(&wanted, &m_obtained);
    }
    if (ret < 0) {
      audio_message(LOG_CRIT, "Couldn't open audio, %s", SDL_GetError());
      return (-1);
    }
  }

  char buffer[128];
  if (Our_SDL_AudioDriverName(buffer, sizeof(buffer)) == NULL) {
    strcpy(buffer, "no audio driver");
  }
  audio_message(LOG_INFO, "got f %d chan %d format %x samples %d size %u %s",
		m_obtained.freq,
		m_obtained.channels,
		m_obtained.format,
		m_obtained.samples,
		m_obtained.size,
		buffer);

#ifdef TEST_MONO_TO_STEREO
#define CHECK_SDL_CHANS_RETURNED  TRUE
#define OBTAINED_CHANS  2
#else
#define CHECK_SDL_CHANS_RETURNED m_obtained.channels != m_channels
#define OBTAINED_CHANS  m_obtained.channels
#endif
  bool need_convert = false;
  if (CHECK_SDL_CHANS_RETURNED) {
    Our_SDL_CloseAudio();
    wanted.channels = OBTAINED_CHANS;
    wanted.format = AUDIO_S16SYS; // we're converting, so always choose
    m_bytes_per_sample_output = sizeof(int16_t) * wanted.channels;
    
    ret = Our_SDL_OpenAudio(&wanted, &m_obtained);
    audio_message(LOG_INFO, 
		  "requested f %d chan %d format %x samples %d",
		  wanted.freq,
		  wanted.channels,
		  wanted.format,
		  wanted.samples);
    if (ret < 0) {
      audio_message(LOG_CRIT, "Couldn't reopen audio, %s", SDL_GetError());
      return (-1);
    }
    audio_message(LOG_INFO, "got f %d chan %d format %x samples %d size %u %s",
		  m_obtained.freq,
		  m_obtained.channels,
		  m_obtained.format,
		  m_obtained.samples,
		  m_obtained.size,
		  buffer);
    need_convert = true;
  } else {
    m_bytes_per_sample_output = m_obtained.channels * bytes_per_sample;
  }

  m_got_channels = m_obtained.channels;
  m_output_buffer_size_bytes = m_obtained.size;

  if (m_decode_format == AUDIO_FMT_FLOAT || need_convert) {
    audio_message(LOG_DEBUG, "convert buffer size is %d", m_obtained.size);
    audio_convert_init(m_obtained.size, m_obtained.samples);
  }

  m_use_SDL_delay = Our_SDL_HasAudioDelay();
  if (m_use_SDL_delay)
    audio_message(LOG_NOTICE, "Using delay measurement from SDL");
  return 1; // check again pretty soon...
}