/* * 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); }
/* * 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; }
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); }
/* * 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; }
// 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; }
// 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... }