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

📄 audio_render.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / Scene Rendering sub-project * *  GPAC 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, or (at your option) *  any later version. *    *  GPAC 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 this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/internal/renderer_dev.h>static GF_Err AR_SetupAudioFormat(GF_AudioRenderer *ar){	GF_Err e;	u32 freq, nb_bits, nb_chan, ch_cfg;	gf_mixer_get_config(ar->mixer, &freq, &nb_chan, &nb_bits, &ch_cfg);	/*user disabled multichannel audio*/	if ((ar->flags && GF_SR_AUDIO_NO_MULTI_CH) && (nb_chan>2)) nb_chan = 2;	e = ar->audio_out->ConfigureOutput(ar->audio_out, &freq, &nb_chan, &nb_bits, ch_cfg);	if (e) {		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[AudioRender] reconfigure error %e\n", e));		if (nb_chan>2) {			nb_chan=2;			e = ar->audio_out->ConfigureOutput(ar->audio_out, &freq, &nb_chan, &nb_bits, ch_cfg);		}		if (e) return e;	}	gf_mixer_set_config(ar->mixer, freq, nb_chan, nb_bits, ch_cfg);	ar->audio_delay = ar->audio_out->GetAudioDelay(ar->audio_out);	ar->audio_out->SetVolume(ar->audio_out, ar->volume);	ar->audio_out->SetPan(ar->audio_out, ar->pan);		return GF_OK;}static u32 AR_FillBuffer(void *ptr, char *buffer, u32 buffer_size){	GF_AudioRenderer *ar = (GF_AudioRenderer *) ptr;	if (!ar->need_reconfig) {		return gf_mixer_get_output(ar->mixer, buffer, buffer_size);	}	return 0;}u32 AR_MainLoop(void *p){	GF_AudioRenderer *ar = (GF_AudioRenderer *) p;	ar->audio_th_state = 1;	GF_LOG(GF_LOG_DEBUG, GF_LOG_CORE, ("[AudioRender] Entering audio thread ID %d\n", gf_th_id() ));	gf_mixer_lock(ar->mixer, 1);	ar->need_reconfig = 1;	gf_sr_ar_reconfig(ar);	gf_mixer_lock(ar->mixer, 0);	while (ar->audio_th_state == 1) {		//GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] Audio simulation step\n"));				/*THIS IS NEEDED FOR SYMBIAN - if no yield here, the audio module always grabs the 		main mixer mutex and it takes forever before it can be grabed by another thread, 		for instance when reconfiguring scene*/		gf_sleep(0);				gf_mixer_lock(ar->mixer, 1);		if (ar->Frozen) {			gf_mixer_lock(ar->mixer, 0);			gf_sleep(33);		} else {			if (ar->need_reconfig) gf_sr_ar_reconfig(ar);			ar->audio_out->WriteAudio(ar->audio_out);			gf_mixer_lock(ar->mixer, 0);		}	}	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] Exiting audio thread\n"));	ar->audio_out->Shutdown(ar->audio_out);	ar->audio_th_state = 3;	return 0;}GF_AudioRenderer *gf_sr_ar_load(GF_User *user){	const char *sOpt;	u32 i, count;	u32 num_buffers, total_duration;	GF_Err e;	GF_AudioRenderer *ar;	ar = (GF_AudioRenderer *) malloc(sizeof(GF_AudioRenderer));	memset(ar, 0, sizeof(GF_AudioRenderer));	num_buffers = total_duration = 0;	sOpt = gf_cfg_get_key(user->config, "Audio", "ForceConfig");	if (sOpt && !stricmp(sOpt, "yes")) {		sOpt = gf_cfg_get_key(user->config, "Audio", "NumBuffers");		num_buffers = sOpt ? atoi(sOpt) : 6;		sOpt = gf_cfg_get_key(user->config, "Audio", "TotalDuration");		total_duration = sOpt ? atoi(sOpt) : 400;	}	sOpt = gf_cfg_get_key(user->config, "Audio", "NoResync");	if (sOpt && !stricmp(sOpt, "yes")) ar->flags |= GF_SR_AUDIO_NO_RESYNC;	sOpt = gf_cfg_get_key(user->config, "Audio", "DisableMultiChannel");	if (sOpt && !stricmp(sOpt, "yes")) ar->flags |= GF_SR_AUDIO_NO_MULTI_CH;		ar->mixer = gf_mixer_new(ar);	ar->user = user;	if (! (user->init_flags & GF_TERM_NO_AUDIO) ) {		/*get a prefered renderer*/		sOpt = gf_cfg_get_key(user->config, "Audio", "DriverName");		if (sOpt) {			ar->audio_out = (GF_AudioOutput *) gf_modules_load_interface_by_name(user->modules, sOpt, GF_AUDIO_OUTPUT_INTERFACE);			if (!ar->audio_out) {				ar->audio_out = NULL;				sOpt = NULL;			}		}		if (!ar->audio_out) {			count = gf_modules_get_count(ar->user->modules);			for (i=0; i<count; i++) {				ar->audio_out = (GF_AudioOutput *) gf_modules_load_interface(ar->user->modules, i, GF_AUDIO_OUTPUT_INTERFACE);				if (!ar->audio_out) continue;				GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] Audio output module %s loaded\n", ar->audio_out->module_name));				/*check that's a valid audio renderer*/				if (ar->audio_out->SelfThreaded) {					if (ar->audio_out->SetPriority) break;				} else {					if (ar->audio_out->WriteAudio) break;				}				gf_modules_close_interface((GF_BaseInterface *)ar->audio_out);				ar->audio_out = NULL;			}		}		/*if not init we run with a NULL audio renderer*/		if (ar->audio_out) {			ar->audio_out->FillBuffer = AR_FillBuffer;			ar->audio_out->audio_renderer = ar;			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] Setting up audio module %s\n", ar->audio_out->module_name));			e = ar->audio_out->Setup(ar->audio_out, ar->user->os_window_handler, num_buffers, total_duration);						/*if audio module is not threaded, reconfigure it from our own thread*///			if (e==GF_OK) e = AR_SetupAudioFormat(ar);			if (e != GF_OK) {				GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("Could not setup audio out %s\n", ar->audio_out->module_name));				gf_modules_close_interface((GF_BaseInterface *)ar->audio_out);				ar->audio_out = NULL;			} else {				/*remember the module we use*/				gf_cfg_set_key(user->config, "Audio", "DriverName", ar->audio_out->module_name);				if (!ar->audio_out->SelfThreaded) {					ar->th = gf_th_new();					gf_th_run(ar->th, AR_MainLoop, ar);				} else {					AR_SetupAudioFormat(ar);					if (ar->audio_out->SetPriority) ar->audio_out->SetPriority(ar->audio_out, GF_THREAD_PRIORITY_REALTIME);				}			}		}		if (!ar->audio_out) gf_cfg_set_key(user->config, "Audio", "DriverName", "No Audio Output Available");	}	sOpt = gf_cfg_get_key(user->config, "Audio", "Volume");	ar->volume = sOpt ? atoi(sOpt) : 75;	sOpt = gf_cfg_get_key(user->config, "Audio", "Pan");	ar->pan = sOpt ? atoi(sOpt) : 50;	/*init renderer timer*/	ar->startTime = gf_sys_clock();	return ar;}void gf_sr_ar_del(GF_AudioRenderer *ar){	if (!ar) return;	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] Destroying renderer\n"));	/*resume if paused (might cause deadlock otherwise)*/	if (ar->Frozen) gf_sr_ar_control(ar, 1);	/*stop and shutdown*/	if (ar->audio_out) {		/*kill audio thread*/		if (!ar->audio_out->SelfThreaded) {			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] stoping audio thread\n"));			ar->audio_th_state = 2;			while (ar->audio_th_state != 3) {				gf_sleep(33);			}			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] audio thread stopped\n"));			gf_th_del(ar->th);			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] audio thread destroyed\n"));		}		/*lock access before shutdown and emulate a reconfig (avoids mixer lock from self-threaded modules)*/		ar->need_reconfig = 1;		gf_mixer_lock(ar->mixer, 1);		if (ar->audio_out->SelfThreaded) ar->audio_out->Shutdown(ar->audio_out);		gf_modules_close_interface((GF_BaseInterface *)ar->audio_out);		gf_mixer_lock(ar->mixer, 0);	}	gf_mixer_del(ar->mixer);	free(ar);	GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[AudioRender] Renderer destroyed\n"));}void gf_sr_ar_reset(GF_AudioRenderer *ar){	gf_mixer_remove_all(ar->mixer);}void AR_FreezeIntern(GF_AudioRenderer *ar, Bool DoFreeze, Bool for_reconfig, Bool reset_hw_buffer){	gf_mixer_lock(ar->mixer, 1);	if (DoFreeze) {		if (!ar->Frozen) {			ar->FreezeTime = gf_sys_clock();			if (!for_reconfig && ar->audio_out && ar->audio_out->Play) ar->audio_out->Play(ar->audio_out, 0);			ar->Frozen = 1;		}	} else {		if (ar->Frozen) {			if (!for_reconfig && ar->audio_out && ar->audio_out->Play) ar->audio_out->Play(ar->audio_out, reset_hw_buffer ? 2 : 1);			ar->Frozen = 0;			ar->startTime += gf_sys_clock() - ar->FreezeTime;		}	}	gf_mixer_lock(ar->mixer, 0);}void gf_sr_ar_control(GF_AudioRenderer *ar, u32 PauseType){	AR_FreezeIntern(ar, !PauseType, 0, (PauseType==2) ? 1 : 0);}void gf_sr_ar_set_volume(GF_AudioRenderer *ar, u32 Volume){		char sOpt[10];	gf_mixer_lock(ar->mixer, 1);	ar->volume = MIN(Volume, 100);	if (ar->audio_out) ar->audio_out->SetVolume(ar->audio_out, ar->volume);	sprintf(sOpt, "%d", ar->volume);	gf_cfg_set_key(ar->user->config, "Audio", "Volume", sOpt);	gf_mixer_lock(ar->mixer, 0);}void gf_sr_ar_set_pan(GF_AudioRenderer *ar, u32 Balance){	gf_mixer_lock(ar->mixer, 1);	ar->pan = MIN(Balance, 100);	if (ar->audio_out) ar->audio_out->SetPan(ar->audio_out, ar->pan);	gf_mixer_lock(ar->mixer, 0);}void gf_sr_ar_add_src(GF_AudioRenderer *ar, GF_AudioInterface *source){	Bool recfg;	if (!ar) return;	/*lock mixer*/	gf_mixer_lock(ar->mixer, 1);	gf_mixer_add_input(ar->mixer, source);	/*if changed reconfig*/	recfg = gf_mixer_reconfig(ar->mixer);	if (!ar->need_reconfig) ar->need_reconfig = recfg;	/*unlock mixer*/	gf_mixer_lock(ar->mixer, 0);}void gf_sr_ar_remove_src(GF_AudioRenderer *ar, GF_AudioInterface *source){	if (ar) gf_mixer_remove_input(ar->mixer, source);}void gf_sr_ar_set_priority(GF_AudioRenderer *ar, u32 priority){	if (ar->audio_out && ar->audio_out->SelfThreaded) {		ar->audio_out->SetPriority(ar->audio_out, priority);	} else {		gf_th_set_priority(ar->th, priority);	}}void gf_sr_ar_reconfig(GF_AudioRenderer *ar){	if (!ar->need_reconfig || !ar->audio_out) return;	/*lock mixer*/	gf_mixer_lock(ar->mixer, 1);	AR_FreezeIntern(ar, 1, 1, 0);	ar->need_reconfig = 0;	AR_SetupAudioFormat(ar);	AR_FreezeIntern(ar, 0, 1, 0);		/*unlock mixer*/	gf_mixer_lock(ar->mixer, 0);}u32 gf_sr_ar_get_delay(GF_AudioRenderer *ar){	return ar->audio_out->GetAudioDelay(ar->audio_out);}u32 gf_sr_ar_get_clock(GF_AudioRenderer *ar){	if (ar->Frozen) return ar->FreezeTime - ar->startTime;	return gf_sys_clock() - ar->startTime;}

⌨️ 快捷键说明

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