⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_audio.cpp

📁 彩信浏览器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// This file is part of Ambulant Player, www.ambulantplayer.org.//// Copyright (C) 2003-2007 Stichting CWI, // Kruislaan 413, 1098 SJ Amsterdam, The Netherlands.//// Ambulant Player is free software; you can redistribute it and/or modify// it under the terms of the GNU Lesser General Public License as published by// the Free Software Foundation; either version 2.1 of the License, or// (at your option) any later version.//// Ambulant Player is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public License// along with Ambulant Player; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA//#define AM_DBG#ifndef AM_DBG#define AM_DBG if(0)#endif#undef HAVE_ICONV#include "ambulant/gui/SDL/sdl_audio.h"#include "ambulant/net/posix_datasource.h"#include "ambulant/common/region_info.h"#include <stdlib.h>using namespace ambulant;//using namespace gui::sdl;extern "C" {void sdl_C_callback(void *userdata, Uint8 *stream, int len){	gui::sdl::sdl_audio_renderer::sdl_callback(stream, len);}}static voidadd_samples(short *outbuf, short *inbuf, int size, float *volumes, int volcount){	int i;	int vol_index = 0;	for(i=0; i<size; i++) {		long value = (long)inbuf[i];		if (volcount) {			value = (long)(value * volumes[vol_index]);			if (++vol_index >= volcount) vol_index = 0;		}		value += (long)outbuf[i];		if (value > 0x7fff) value = 0x7fff;		else if (value < -0x7fff) value = -0x7fff;		outbuf[i] = (short)value;	}}typedef lib::no_arg_callback<gui::sdl::sdl_audio_renderer> readdone_callback;	// ************************************************************bool gui::sdl::sdl_audio_renderer::s_sdl_init = false;Uint16 gui::sdl::sdl_audio_renderer::s_sdl_format = AUDIO_S16SYS;net::audio_format gui::sdl::sdl_audio_renderer::s_ambulant_format = net::audio_format(44100, 2, 16);int gui::sdl::sdl_audio_renderer::s_buffer_size = 4096;int gui::sdl::sdl_audio_renderer::s_min_buffer_size_bytes = 2 * 4096 * 2 * 2;  lib::critical_section gui::sdl::sdl_audio_renderer::s_static_lock;    std::list<gui::sdl::sdl_audio_renderer *> gui::sdl::sdl_audio_renderer::s_renderers;intgui::sdl::sdl_audio_renderer::init(){	s_static_lock.enter();	if (s_sdl_init) {		s_static_lock.leave();		return 0;	}    int err = 0;		// XXXX Should check that s_ambulant_format and s_sdl_format match!		// Step one - initialize the SDL library	err = SDL_Init(SDL_INIT_AUDIO| SDL_INIT_NOPARACHUTE);	if (err < 0) {		lib::logger::get_logger()->trace("sdl_audio_renderer.init: SDL_Init failed: error %d", err);		lib::logger::get_logger()->error(gettext("Cannot initialize SDL audio library"));		s_static_lock.leave();		return err;	}		// Step three - open the mixer	SDL_AudioSpec desired, obtained;	(void) memset(&desired, 0, sizeof(SDL_AudioSpec));	(void) memset(&obtained, 0, sizeof(SDL_AudioSpec));	desired.freq = s_ambulant_format.samplerate;	desired.format = s_sdl_format;	desired.channels = s_ambulant_format.channels;	desired.samples = s_buffer_size;	desired.callback = sdl_C_callback;	desired.userdata = NULL;	err = SDL_OpenAudio(&desired, &obtained);	if (err < 0) {		lib::logger::get_logger()->trace("sdl_renderer_playable_ds.init: SDL_OpenAudio failed: error %d", err);		lib::logger::get_logger()->error(gettext("Cannot open SDL audio output stream"));		s_static_lock.leave();    	return err;	}	s_ambulant_format.samplerate = obtained.freq;	s_ambulant_format.channels = obtained.channels;	if (obtained.format != s_sdl_format) {		lib::logger::get_logger()->trace("sdl_renderer_playable_ds.init: SDL_OpenAudio could not support format 0x%x, returned 0x%x",			s_sdl_format, obtained.format);		lib::logger::get_logger()->error(gettext("Cannot open SDL audio output stream with required characteristics"));		s_static_lock.leave();		return -1;	}	AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer.init: SDL init succes");				s_sdl_init = true;	s_static_lock.leave();	return err;}voidgui::sdl::sdl_audio_renderer::register_renderer(sdl_audio_renderer *rnd){	s_static_lock.enter();	AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::register_renderer(0x%x)", rnd);	std::list<sdl_audio_renderer *>::iterator i;	for( i=s_renderers.begin(); i != s_renderers.end(); i++) {		if ((*i) == rnd) {			AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::register_renderer() already exists !");			s_static_lock.leave();			return;		}	}	s_renderers.push_back(rnd);	AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::register_renderer: unpause SDL");	SDL_PauseAudio(0);	s_static_lock.leave();}voidgui::sdl::sdl_audio_renderer::unregister_renderer(sdl_audio_renderer *rnd){	s_static_lock.enter();	AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::unregister_renderer(0x%x)", rnd);	std::list<sdl_audio_renderer *>::iterator i;	for( i=s_renderers.begin(); i != s_renderers.end(); i++) {		if ((*i) == rnd) {			s_renderers.erase(i);			break;		}	}	if (s_renderers.size() == 0) {		AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::register_renderer: pause SDL");		SDL_PauseAudio(1);	}	s_static_lock.leave();}voidgui::sdl::sdl_audio_renderer::sdl_callback(Uint8 *stream, int len){	s_static_lock.enter();	std::list<sdl_audio_renderer *>::iterator first = s_renderers.begin();	if (s_renderers.size() == 1 && (*first)->m_volcount == 0	    && ! ((*first)->m_intransition || (*first)->m_outtransition)	    ) {		// Exactly one active stream, no volume/pan processing,		// no transitions: use simple copy		Uint8 *single_data;		AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::sdl_callback(0x%x, %d) [one stream] calling get_data()", (void*) stream, len);		int single_len = (*first)->get_data(len, &single_data);		assert(single_len <= len);		if (single_len != 0) {			assert(single_data);			memcpy(stream, single_data, std::min(len, single_len));		}		AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::sdl_callback(0x%x, %d) [one stream] calling get_data_done(%d)", (void*) stream, len, single_len);		(*first)->get_data_done(single_len);		if (single_len < len)			memset(stream+single_len, 0, (len-single_len));	} else {		// No streams, or more than one: use an accumulation buffer		memset(stream, 0, len);		std::list<sdl_audio_renderer *>::iterator i;		for (i=first; i != s_renderers.end(); i++) {			Uint8 *next_data;			AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::sdl_callback(0x%x, %d))calling get_data() ", (void*) stream, len);			int next_len = (*i)->get_data(len, &next_data);			if (next_len)				add_samples((short*)stream, (short*)next_data, std::min(len/2, next_len/2), (*i)->m_volumes, (*i)->m_volcount);			AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::sdl_callback(0x%x, %d))calling get_data_done(%d) ", (void*) stream, len, next_len);			(*i)->get_data_done(next_len);		}	}	s_static_lock.leave();}// ************************************************************gui::sdl::sdl_audio_renderer::sdl_audio_renderer(	common::playable_notification *context,	common::playable_notification::cookie_type cookie,	const lib::node *node,	lib::event_processor *evp,	common::factories *factory):	common::renderer_playable(context, cookie, node, evp),	m_audio_src(NULL),	m_is_playing(false),	m_is_paused(false),	m_read_ptr_called(false),	m_volcount(0),	m_intransition(NULL),	m_outtransition(NULL),	m_transition_engine(NULL){	AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::sdl_audio_renderer() -> 0x%x",  this);	if (init() != 0)		return;			net::audio_format_choices supported(s_ambulant_format);	net::url url = node->get_url("src");		_init_clip_begin_end();		m_audio_src = factory->get_datasource_factory()->new_audio_datasource(url, supported, m_clip_begin, m_clip_end);	if (!m_audio_src)		lib::logger::get_logger()->error(gettext("%s: cannot open audio file"), repr(url).c_str());	else if (!supported.contains(m_audio_src->get_audio_format())) {		lib::logger::get_logger()->error(gettext("%s: audio format not supported"), repr(url).c_str());		m_audio_src->release();		m_audio_src = NULL;	}}gui::sdl::sdl_audio_renderer::sdl_audio_renderer(    common::playable_notification *context,    common::playable_notification::cookie_type cookie,    const lib::node *node,    lib::event_processor *evp,	common::factories* factory,	net::audio_datasource *ds):	common::renderer_playable(context, cookie, node, evp),	m_audio_src(ds),	m_is_playing(false),	m_is_paused(false),	m_read_ptr_called(false),	m_intransition(NULL),	m_outtransition(NULL),	m_transition_engine(NULL){	net::audio_format_choices supported(s_ambulant_format);	net::url url = node->get_url("src");	AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::sdl_audio_renderer() this=(x%x), ds = 0x%x",  (void*) this, (void*) ds);	if (init() != 0)		return;			if (!m_audio_src)		lib::logger::get_logger()->error(gettext("%s: cannot open"), repr(url).c_str());		// Ugly hack to get the resampler.	if (m_audio_src) {		net::audio_datasource *resample_ds = factory->get_datasource_factory()->new_audio_filter(url, supported, ds);		AM_DBG lib::logger::get_logger ()->debug("sdl_audio_renderer::sdl_audio_renderer() (this =0x%x) got resample datasource 0x%x", (void *) this, resample_ds);		if (resample_ds) {			m_audio_src = resample_ds;			AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer: opened resample datasource !");		}	}}gui::sdl::sdl_audio_renderer::~sdl_audio_renderer(){	m_lock.enter();	AM_DBG lib::logger::get_logger()->debug("sdl_audio_renderer::~sdl_audio_renderer(0x%x) m_audio_src=0x%x",  this, m_audio_src);			if (m_is_playing) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -