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

📄 coreaudio.c

📁 mips上编译过的mpg 运行正常 环境:AU12
💻 C
字号:
/*	coreaudio: audio output on MacOS X	copyright ?-2006 by the mpg123 project - free software under the terms of the GPL 2	see COPYING and AUTHORS files in distribution or http://mpg123.org	initially written by Guillaume Outters	modified by Nicholas J Humfrey to use SFIFO code	modified by Taihei Monma to use AudioUnit and AudioConverter APIs*/#include "sfifo.h"#include "mpg123app.h"#include <CoreServices/CoreServices.h>#include <AudioUnit/AudioUnit.h>#include <AudioToolbox/AudioToolbox.h>#include <errno.h>#include "debug.h"#define FIFO_DURATION		(0.5f)		/* Duration of the ring buffer in seconds */typedef struct mpg123_coreaudio{	AudioConverterRef converter;	AudioUnit outputUnit;	int open;	char play;	int channels;	int last_buffer;	int play_done;	int decode_done;		/* Convertion buffer */	unsigned char * buffer;	size_t buffer_size;		/* Ring buffer */	sfifo_t fifo;} mpg123_coreaudio_t;static OSStatus playProc(AudioConverterRef inAudioConverter,						 UInt32 *ioNumberDataPackets,                         AudioBufferList *outOutputData,                         AudioStreamPacketDescription **outDataPacketDescription,                         void* inClientData){	mpg123_coreaudio_t *ca = (mpg123_coreaudio_t *)inClientData;	long n;			if(ca->last_buffer) {		ca->play_done = 1;		return noErr;	}		for(n = 0; n < outOutputData->mNumberBuffers; n++)	{		unsigned int wanted = *ioNumberDataPackets * ca->channels * 2;		unsigned char *dest;		unsigned int read;		if(ca->buffer_size < wanted) {			debug1("Allocating %d byte sample conversion buffer", wanted);			ca->buffer = realloc( ca->buffer, wanted);			ca->buffer_size = wanted;		}		dest = ca->buffer;				/* Only play if we have data left */		if ( sfifo_used( &ca->fifo ) < wanted ) {			if(!ca->decode_done) {				warning("Didn't have any audio data in callback (buffer underflow)");				return -1;			}			wanted = sfifo_used( &ca->fifo );			ca->last_buffer = 1;		}				/* Read audio from FIFO to SDL's buffer */		read = sfifo_read( &ca->fifo, dest, wanted );				if (wanted!=read)			warning2("Error reading from the ring buffer (wanted=%u, read=%u).\n", wanted, read);				outOutputData->mBuffers[n].mDataByteSize = read;		outOutputData->mBuffers[n].mData = dest;	}		return noErr; }static OSStatus convertProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags,                            const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,                            UInt32 inNumFrames, AudioBufferList *ioData){	AudioStreamPacketDescription* outPacketDescription = NULL;	mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)inRefCon;	OSStatus err= noErr;		err = AudioConverterFillComplexBuffer(ca->converter, playProc, inRefCon, &inNumFrames, ioData, outPacketDescription);		return err;}static int open_coreaudio(audio_output_t *ao){	mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)ao->userptr;	UInt32 size;	ComponentDescription desc;	Component comp;	AudioStreamBasicDescription inFormat;	AudioStreamBasicDescription outFormat;	AURenderCallbackStruct  renderCallback;	Boolean outWritable;		/* Initialize our environment */	ca->play = 0;	ca->buffer = NULL;	ca->buffer_size = 0;	ca->last_buffer = 0;	ca->play_done = 0;	ca->decode_done = 0;		/* Get the default audio output unit */	desc.componentType = kAudioUnitType_Output; 	desc.componentSubType = kAudioUnitSubType_DefaultOutput;	desc.componentManufacturer = kAudioUnitManufacturer_Apple;	desc.componentFlags = 0;	desc.componentFlagsMask = 0;	comp = FindNextComponent(NULL, &desc);	if(comp == NULL) {		error("FindNextComponent failed");		return(-1);	}		if(OpenAComponent(comp, &(ca->outputUnit)))  {		error("OpenAComponent failed");		return (-1);	}		if(AudioUnitInitialize(ca->outputUnit)) {		error("AudioUnitInitialize failed");		return (-1);	}		/* Specify the output PCM format */	AudioUnitGetPropertyInfo(ca->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &size, &outWritable);	if(AudioUnitGetProperty(ca->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &outFormat, &size)) {		error("AudioUnitGetProperty(kAudioUnitProperty_StreamFormat) failed");		return (-1);	}		if(AudioUnitSetProperty(ca->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outFormat, size)) {		error("AudioUnitSetProperty(kAudioUnitProperty_StreamFormat) failed");		return (-1);	}		/* Specify the input PCM format */	ca->channels = ao->channels;	inFormat.mSampleRate = ao->rate;	inFormat.mChannelsPerFrame = ao->channels;	inFormat.mBitsPerChannel = 16;	inFormat.mBytesPerPacket = 2*inFormat.mChannelsPerFrame;	inFormat.mFramesPerPacket = 1;	inFormat.mBytesPerFrame = 2*inFormat.mChannelsPerFrame;	inFormat.mFormatID = kAudioFormatLinearPCM;#ifdef _BIG_ENDIAN	inFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian;#else	inFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;#endif				/* Add our callback - but don't start it yet */	memset(&renderCallback, 0, sizeof(AURenderCallbackStruct));	renderCallback.inputProc = convertProc;	renderCallback.inputProcRefCon = ao->userptr;	if(AudioUnitSetProperty(ca->outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(AURenderCallbackStruct))) {		error("AudioUnitSetProperty(kAudioUnitProperty_SetRenderCallback) failed");		return(-1);	}			/* Open an audio I/O stream and create converter */	if (ao->rate > 0 && ao->channels >0 ) {		int ringbuffer_len;		if(AudioConverterNew(&inFormat, &outFormat, &(ca->converter))) {			error("AudioConverterNew failed");			return(-1);		}		if(ao->channels == 1) {			SInt32 channelMap[2] = { 0, 0 };			if(AudioConverterSetProperty(ca->converter, kAudioConverterChannelMap, sizeof(channelMap), channelMap)) {				error("AudioConverterSetProperty(kAudioConverterChannelMap) failed");				return(-1);			}		}				/* Initialise FIFO */		ringbuffer_len = ao->rate * FIFO_DURATION * sizeof(short) *ao->channels;		debug2( "Allocating %d byte ring-buffer (%f seconds)", ringbuffer_len, (float)FIFO_DURATION);		sfifo_init( &ca->fifo, ringbuffer_len );									   	}		return(0);}static int get_formats_coreaudio(audio_output_t *ao){	/* Only support Signed 16-bit output */	return MPG123_ENC_SIGNED_16;}static int write_coreaudio(audio_output_t *ao, unsigned char *buf, int len){	mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)ao->userptr;	int written;	/* If there is no room, then sleep for half the length of the FIFO */	while (sfifo_space( &ca->fifo ) < len ) {		usleep( (FIFO_DURATION/2) * 1000000 );	}		/* Store converted audio in ring buffer */	written = sfifo_write( &ca->fifo, (char*)buf, len);	if (written != len) {		warning( "Failed to write audio to ring buffer" );		return -1;	}		/* Start playback now that we have something to play */	if(!ca->play)	{		if(AudioOutputUnitStart(ca->outputUnit)) {			error("AudioOutputUnitStart failed");			return(-1);		}		ca->play = 1;	}		return len;}static int close_coreaudio(audio_output_t *ao){	mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)ao->userptr;	if (ca) {		ca->decode_done = 1;		while(!ca->play_done && ca->play) usleep(10000);				/* No matter the error code, we want to close it (by brute force if necessary) */		AudioConverterDispose(ca->converter);		AudioOutputUnitStop(ca->outputUnit);		AudioUnitUninitialize(ca->outputUnit);		CloseComponent(ca->outputUnit);		    /* Free the ring buffer */		sfifo_close( &ca->fifo );				/* Free the conversion buffer */		if (ca->buffer) {			free( ca->buffer );			ca->buffer = NULL;		}			}		return 0;}static void flush_coreaudio(audio_output_t *ao){	mpg123_coreaudio_t* ca = (mpg123_coreaudio_t*)ao->userptr;	/* Stop playback */	if(AudioOutputUnitStop(ca->outputUnit)) {		error("AudioOutputUnitStop failed");	}	ca->play=0;		/* Empty out the ring buffer */	sfifo_flush( &ca->fifo );	}static int deinit_coreaudio(audio_output_t* ao){	/* Free up memory */	if (ao->userptr) {		free( ao->userptr );		ao->userptr = NULL;	}	/* Success */	return 0;}static int init_coreaudio(audio_output_t* ao){	if (ao==NULL) return -1;	/* Set callbacks */	ao->open = open_coreaudio;	ao->flush = flush_coreaudio;	ao->write = write_coreaudio;	ao->get_formats = get_formats_coreaudio;	ao->close = close_coreaudio;	ao->deinit = deinit_coreaudio;	/* Allocate memory for data structure */	ao->userptr = malloc( sizeof( mpg123_coreaudio_t ) );	if (ao->userptr==NULL) {		error("failed to malloc memory for 'mpg123_coreaudio_t'");		return -1;	}	memset( ao->userptr, 0, sizeof(mpg123_coreaudio_t) );	/* Success */	return 0;}/* 	Module information data structure*/mpg123_module_t mpg123_output_module_info = {	/* api_version */	MPG123_MODULE_API_VERSION,	/* name */			"coreaudio",							/* description */	"Output audio using Mac OS X's CoreAudio.",	/* revision */		"$Rev:$",	/* handle */		NULL,		/* init_output */	init_coreaudio,						};

⌨️ 快捷键说明

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