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

📄 audio_macosx.c

📁 mpeg 2 source code for video compression
💻 C
字号:
/*	audio_macosx: 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.de	initially written by Guillaume Outters	modified by Nicholas J Humfrey to use SFIFO code*/#include "config.h"#include "debug.h"#include "sfifo.h"#include "mpg123.h"#include <CoreAudio/AudioHardware.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#define FIFO_DURATION		(0.5f)struct anEnv{	AudioDeviceID device;	char play;		/* Convertion buffer */	float * buffer;	size_t buffer_size;		/* Ring buffer */	sfifo_t fifo;};static struct anEnv *env=NULL;static OSStatus playProc(AudioDeviceID inDevice, const AudioTimeStamp * inNow,						 const AudioBufferList * inInputData, const AudioTimeStamp * inInputTime,                         AudioBufferList * outOutputData, const AudioTimeStamp * inOutputTime, void * inClientData){		long n;		for(n = 0; n < outOutputData->mNumberBuffers; n++)	{		unsigned int wanted = outOutputData->mBuffers[n].mDataByteSize;		unsigned char *dest = outOutputData->mBuffers[n].mData;		unsigned int read;				/* Only play if we have data left */		if ( sfifo_used( &env->fifo ) < wanted ) {			warning("Didn't have any audio data in callback (buffer underflow)");			return -1;		}				/* Read audio from FIFO to SDL's buffer */		read = sfifo_read( &env->fifo, dest, wanted );				if (wanted!=read)			warning2("Error reading from the ring buffer (wanted=%u, read=%u).\n", wanted, read);			}		return (0); }int audio_open(struct audio_info_struct *ai){	AudioStreamBasicDescription format;	Float64 devicerate;	UInt32 size;		/* Allocate memory for data structure */	if (!env) {		env = (struct anEnv*)malloc( sizeof( struct anEnv ) );		if (!env) {			perror("failed to malloc memory for 'struct anEnv'");			exit(-1);		}	}	/* Initialize our environment */	env->device = 0;	env->play = 0;	env->buffer = NULL;	env->buffer_size = 0;			/* Get the default audio output device */	size = sizeof(env->device);	if(AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &env->device)) {		error("AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice) failed");		return(-1);	}		/* Ensure that the device supports PCM */	size = sizeof(format);	if(AudioDeviceGetProperty(env->device, 0, 0, kAudioDevicePropertyStreamFormat, &size, &format)) {		fprintf(stderr, "AudioDeviceGetProperty(kAudioDevicePropertyStreamFormat) failed");		return(-1);	}	if(format.mFormatID != kAudioFormatLinearPCM) {		error("format.mFormatID != kAudioFormatLinearPCM");		return(-1);	}		/* Get the nominal sample rate of the device */	size = sizeof(devicerate);	if(AudioDeviceGetProperty(env->device, 0, 0, kAudioDevicePropertyNominalSampleRate, &size, &devicerate)) {		fprintf(stderr, "AudioDeviceGetProperty(kAudioDevicePropertyNominalSampleRate) failed");		return(-1);	}			/* Add our callback - but don't start it yet */	if(AudioDeviceAddIOProc(env->device, playProc, env)) {		error("AudioDeviceAddIOProc failed");		return(-1);	}			/* Open an audio I/O stream. */	if (ai->rate > 0 && ai->channels >0 ) {		int ringbuffer_len;				/* Check sample rate */		if (devicerate != ai->rate) {			error2("Error: sample rate of device doesn't match playback rate (%d != %d)", (int)devicerate, (int)ai->rate);			return(-1);		}				/* Initialise FIFO */		ringbuffer_len = ai->rate * FIFO_DURATION * sizeof(float) *ai->channels;		debug2( "Allocating %d byte ring-buffer (%f seconds)", ringbuffer_len, (float)FIFO_DURATION);		sfifo_init( &env->fifo, ringbuffer_len );									   	}		return(0);}int audio_get_formats(struct audio_info_struct *ai){	/* Only support Signed 16-bit output */	return AUDIO_FORMAT_SIGNED_16;}int audio_play_samples(struct audio_info_struct *ai, unsigned char *buf, int len){	short *src = (short *)buf;	int samples = len/sizeof(short);	int flen = samples*sizeof(float);	int written, n;	/* If there is no room, then sleep for half the length of the FIFO */	while (sfifo_space( &env->fifo ) < flen ) {		usleep( (FIFO_DURATION/2) * 1000000 );	}	/* Ensure conversion buffer is big enough */	if (env->buffer_size < flen) {		debug1("Allocating %d byte sample conversion buffer", flen);		env->buffer = realloc( env->buffer, flen);		env->buffer_size = flen;	}		/* Convert audio samples to 32-bit float */	for( n=0; n<samples; n++) {		env->buffer[n] = src[n] / 32768.0f;	}		/* Store converted audio in ring buffer */	written = sfifo_write( &env->fifo, (char*)env->buffer, flen);	if (written != flen) {		warning( "Failed to write audio to ring buffer" );		return -1;	}		/* Start playback now that we have something to play */	if(!env->play)	{		if(AudioDeviceStart(env->device, playProc)) {			error("AudioDeviceStart failed");			return(-1);		}		env->play = 1;	}		return len;}int audio_close(struct audio_info_struct *ai){	if (env) {		/* No matter the error code, we want to close it (by brute force if necessary) */		AudioDeviceStop(env->device, playProc);		AudioDeviceRemoveIOProc(env->device, playProc);		    /* Free the ring buffer */		sfifo_close( &env->fifo );				/* Free the conversion buffer */		if (env->buffer) free( env->buffer );				/* Free environment data structure */		free(env);		env=NULL;	}		return 0;}void audio_queueflush(struct audio_info_struct *ai){	/* Stop playback */	if(AudioDeviceStop(env->device, playProc)) {		error("AudioDeviceStop failed");	}	env->play=0;		/* Empty out the ring buffer */	sfifo_flush( &env->fifo );	}

⌨️ 快捷键说明

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