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

📄 sndfile-play.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
	audio_data = (MacOSXAudioData*) client_data ;	size = data_out->mBuffers [0].mDataByteSize ;	sample_count = size / sizeof (float) ;	buffer = (float*) data_out->mBuffers [0].mData ;	if (audio_data->fake_stereo != 0)	{	read_count = sf_read_float (audio_data->sndfile, buffer, sample_count / 2) ;		for (k = read_count - 1 ; k >= 0 ; k--)		{	buffer [2 * k	] = buffer [k] ;			buffer [2 * k + 1] = buffer [k] ;			} ;		read_count *= 2 ;		}	else		read_count = sf_read_float (audio_data->sndfile, buffer, sample_count) ;	/* Fill the remainder with zeroes. */	if (read_count < sample_count)	{	if (audio_data->fake_stereo == 0)			memset (&(buffer [read_count]), 0, (sample_count - read_count) * sizeof (float)) ;		/* Tell the main application to terminate. */		audio_data->done_playing = SF_TRUE ;		} ;	return noErr ;} /* macosx_audio_out_callback */static voidmacosx_play (int argc, char *argv []){	MacOSXAudioData 	audio_data ;	OSStatus	err ;	UInt32		count, buffer_size ;	int 		k ;	audio_data.fake_stereo = 0 ;	audio_data.device = kAudioDeviceUnknown ;	/*  get the default output device for the HAL */	count = sizeof (AudioDeviceID) ;	if ((err = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice,				&count, (void *) &(audio_data.device))) != noErr)	{	printf ("AudioHardwareGetProperty (kAudioDevicePropertyDefaultOutputDevice) failed.\n") ;		return ;		} ;	/*  get the buffersize that the default device uses for IO */	count = sizeof (UInt32) ;	if ((err = AudioDeviceGetProperty (audio_data.device, 0, false, kAudioDevicePropertyBufferSize,				&count, &buffer_size)) != noErr)	{	printf ("AudioDeviceGetProperty (kAudioDevicePropertyBufferSize) failed.\n") ;		return ;		} ;	/*  get a description of the data format used by the default device */	count = sizeof (AudioStreamBasicDescription) ;	if ((err = AudioDeviceGetProperty (audio_data.device, 0, false, kAudioDevicePropertyStreamFormat,				&count, &(audio_data.format))) != noErr)	{	printf ("AudioDeviceGetProperty (kAudioDevicePropertyStreamFormat) failed.\n") ;		return ;		} ;	/* Base setup completed. Now play files. */	for (k = 1 ; k < argc ; k++)	{	printf ("Playing %s\n", argv [k]) ;		if (! (audio_data.sndfile = sf_open (argv [k], SFM_READ, &(audio_data.sfinfo))))		{	puts (sf_strerror (NULL)) ;			continue ;			} ;		if (audio_data.sfinfo.channels < 1 || audio_data.sfinfo.channels > 2)		{	printf ("Error : channels = %d.\n", audio_data.sfinfo.channels) ;			continue ;			} ;		audio_data.format.mSampleRate = audio_data.sfinfo.samplerate ;		if (audio_data.sfinfo.channels == 1)		{	audio_data.format.mChannelsPerFrame = 2 ;			audio_data.fake_stereo = 1 ;			}		else		audio_data.format.mChannelsPerFrame = audio_data.sfinfo.channels ;		if ((err = AudioDeviceSetProperty (audio_data.device, NULL, 0, false, kAudioDevicePropertyStreamFormat,					sizeof (AudioStreamBasicDescription), &(audio_data.format))) != noErr)		{	printf ("AudioDeviceSetProperty (kAudioDevicePropertyStreamFormat) failed.\n") ;			return ;			} ;		/*  we want linear pcm */		if (audio_data.format.mFormatID != kAudioFormatLinearPCM)			return ;		/* Fire off the device. */		if ((err = AudioDeviceAddIOProc (audio_data.device, macosx_audio_out_callback,				(void *) &audio_data)) != noErr)		{	printf ("AudioDeviceAddIOProc failed.\n") ;			return ;			} ;		err = AudioDeviceStart (audio_data.device, macosx_audio_out_callback) ;		if	(err != noErr)			return ;		audio_data.done_playing = SF_FALSE ;		while (audio_data.done_playing == SF_FALSE)			usleep (10 * 1000) ; /* 10 000 milliseconds. */		if ((err = AudioDeviceStop (audio_data.device, macosx_audio_out_callback)) != noErr)		{	printf ("AudioDeviceStop failed.\n") ;			return ;			} ;		err = AudioDeviceRemoveIOProc (audio_data.device, macosx_audio_out_callback) ;		if (err != noErr)		{	printf ("AudioDeviceRemoveIOProc failed.\n") ;			return ;			} ;		sf_close (audio_data.sndfile) ;		} ;	return ;} /* macosx_play */#endif /* MacOSX *//*------------------------------------------------------------------------------**	Win32 functions for playing a sound.****	This API sucks. Its needlessly complicated and is *WAY* too loose with**	passing pointers arounf in integers and and using char* pointers to**  point to data instead of short*. It plain sucks!*/#if (OS_IS_WIN32 == 1)#define	WIN32_BUFFER_LEN	(1<<15)typedef struct{	HWAVEOUT	hwave ;	WAVEHDR		whdr [2] ;	CRITICAL_SECTION	mutex ;		/* to control access to BuffersInUSe */	HANDLE		Event ;			/* signal that a buffer is free */	short		buffer [WIN32_BUFFER_LEN / sizeof (short)] ;	int			current, bufferlen ;	int			BuffersInUse ;	SNDFILE 	*sndfile ;	SF_INFO 	sfinfo ;	sf_count_t	remaining ;} Win32_Audio_Data ;static voidwin32_play_data (Win32_Audio_Data *audio_data){	int thisread, readcount ;	/* fill a buffer if there is more data and we can read it sucessfully */	readcount = (audio_data->remaining > audio_data->bufferlen) ? audio_data->bufferlen : (int) audio_data->remaining ;	thisread = (int) sf_read_short (audio_data->sndfile, (short *) (audio_data->whdr [audio_data->current].lpData), readcount) ;	audio_data->remaining -= thisread ;	if (thisread > 0)	{	/* Fix buffer length if this is only a partial block. */		if (thisread < audio_data->bufferlen)			audio_data->whdr [audio_data->current].dwBufferLength = thisread * sizeof (short) ;		/* Queue the WAVEHDR */		waveOutWrite (audio_data->hwave, (LPWAVEHDR) &(audio_data->whdr [audio_data->current]), sizeof (WAVEHDR)) ;		/* count another buffer in use */		EnterCriticalSection (&audio_data->mutex) ;		audio_data->BuffersInUse ++ ;		LeaveCriticalSection (&audio_data->mutex) ;		/* use the other buffer next time */		audio_data->current = (audio_data->current + 1) % 2 ;		} ;	return ;} /* win32_play_data */static void CALLBACKwin32_audio_out_callback (HWAVEOUT hwave, UINT msg, DWORD data, DWORD param1, DWORD param2){	Win32_Audio_Data	*audio_data ;	/* Prevent compiler warnings. */	hwave = hwave ;	param1 = param2 ;	if (data == 0)		return ;	/*	** I consider this technique of passing a pointer via an integer as	** fundamentally broken but thats the way microsoft has defined the	** interface.	*/	audio_data = (Win32_Audio_Data*) data ;	/* let main loop know a buffer is free */	if (msg == MM_WOM_DONE)	{	EnterCriticalSection (&audio_data->mutex) ;		audio_data->BuffersInUse -- ;		LeaveCriticalSection (&audio_data->mutex) ;		SetEvent (audio_data->Event) ;		} ;	return ;} /* win32_audio_out_callback *//* This is needed for earlier versions of the M$ development tools. */#ifndef DWORD_PTR#define DWORD_PTR DWORD#endifstatic voidwin32_play (int argc, char *argv []){	Win32_Audio_Data	audio_data ;	WAVEFORMATEX wf ;	int	k, error ;	audio_data.sndfile = NULL ;	audio_data.hwave = 0 ;	for (k = 1 ; k < argc ; k++)	{	printf ("Playing %s\n", argv [k]) ;		if (! (audio_data.sndfile = sf_open (argv [k], SFM_READ, &(audio_data.sfinfo))))		{	puts (sf_strerror (NULL)) ;			continue ;			} ;		audio_data.remaining = audio_data.sfinfo.frames ;		audio_data.current = 0 ;		InitializeCriticalSection (&audio_data.mutex) ;		audio_data.Event = CreateEvent (0, FALSE, FALSE, 0) ;		wf.nChannels = audio_data.sfinfo.channels ;		wf.wFormatTag = WAVE_FORMAT_PCM ;		wf.cbSize = 0 ;		wf.wBitsPerSample = 16 ;		wf.nSamplesPerSec = audio_data.sfinfo.samplerate ;		wf.nBlockAlign = audio_data.sfinfo.channels * sizeof (short) ;		wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec ;		error = waveOutOpen (&(audio_data.hwave), WAVE_MAPPER, &wf, (DWORD_PTR) win32_audio_out_callback,							(DWORD_PTR) &audio_data, CALLBACK_FUNCTION) ;		if (error)		{	puts ("waveOutOpen failed.") ;			audio_data.hwave = 0 ;			continue ;			} ;		audio_data.whdr [0].lpData = (char*) audio_data.buffer ;		audio_data.whdr [1].lpData = ((char*) audio_data.buffer) + sizeof (audio_data.buffer) / 2 ;		audio_data.whdr [0].dwBufferLength = sizeof (audio_data.buffer) / 2 ;		audio_data.whdr [1].dwBufferLength = sizeof (audio_data.buffer) / 2 ;		audio_data.whdr [0].dwFlags = 0 ;		audio_data.whdr [1].dwFlags = 0 ;		/* length of each audio buffer in samples */		audio_data.bufferlen = sizeof (audio_data.buffer) / 2 / sizeof (short) ;		/* Prepare the WAVEHDRs */		if ((error = waveOutPrepareHeader (audio_data.hwave, &(audio_data.whdr [0]), sizeof (WAVEHDR))))		{	printf ("waveOutPrepareHeader [0] failed : %08X\n", error) ;			waveOutClose (audio_data.hwave) ;			continue ;			} ;		if ((error = waveOutPrepareHeader (audio_data.hwave, &(audio_data.whdr [1]), sizeof (WAVEHDR))))		{	printf ("waveOutPrepareHeader [1] failed : %08X\n", error) ;			waveOutUnprepareHeader (audio_data.hwave, &(audio_data.whdr [0]), sizeof (WAVEHDR)) ;			waveOutClose (audio_data.hwave) ;			continue ;			} ;		/* Fill up both buffers with audio data */		audio_data.BuffersInUse = 0 ;		win32_play_data (&audio_data) ;		win32_play_data (&audio_data) ;		/* loop until both buffers are released */		while (audio_data.BuffersInUse > 0)		{			/* wait for buffer to be released */			WaitForSingleObject (audio_data.Event, INFINITE) ;			/* refill the buffer if there is more data to play */			win32_play_data (&audio_data) ;			} ;		waveOutUnprepareHeader (audio_data.hwave, &(audio_data.whdr [0]), sizeof (WAVEHDR)) ;		waveOutUnprepareHeader (audio_data.hwave, &(audio_data.whdr [1]), sizeof (WAVEHDR)) ;		waveOutClose (audio_data.hwave) ;		audio_data.hwave = 0 ;		DeleteCriticalSection (&audio_data.mutex) ;		sf_close (audio_data.sndfile) ;		} ;} /* win32_play */#endif /* Win32 *//*------------------------------------------------------------------------------**	Solaris.*/#if (defined (sun) && defined (unix)) /* ie Solaris */static voidsolaris_play (int argc, char *argv []){	static short 	buffer [BUFFER_LEN] ;	audio_info_t	audio_info ;	SNDFILE			*sndfile ;	SF_INFO			sfinfo ;	unsigned long	delay_time ;	long			k, start_count, output_count, write_count, read_count ;	int				audio_fd, error, done ;	for (k = 1 ; k < argc ; k++)	{	printf ("Playing %s\n", argv [k]) ;		if (! (sndfile = sf_open (argv [k], SFM_READ, &sfinfo)))		{	puts (sf_strerror (NULL)) ;			continue ;			} ;		if (sfinfo.channels < 1 || sfinfo.channels > 2)		{	printf ("Error : channels = %d.\n", sfinfo.channels) ;			continue ;			} ;		/* open the audio device - write only, non-blocking */		if ((audio_fd = open ("/dev/audio", O_WRONLY | O_NONBLOCK)) < 0)		{	perror ("open (/dev/audio) failed") ;			return ;			} ;		/*	Retrive standard values. */		AUDIO_INITINFO (&audio_info) ;		audio_info.play.sample_rate = sfinfo.samplerate ;		audio_info.play.channels = sfinfo.channels ;		audio_info.play.precision = 16 ;		audio_info.play.encoding = AUDIO_ENCODING_LINEAR ;		audio_info.play.gain = AUDIO_MAX_GAIN ;		audio_info.play.balance = AUDIO_MID_BALANCE ;		if ((error = ioctl (audio_fd, AUDIO_SETINFO, &audio_info)))		{	perror ("ioctl (AUDIO_SETINFO) failed") ;			return ;			} ;		/* Delay time equal to 1/4 of a buffer in microseconds. */		delay_time = (BUFFER_LEN * 1000000) / (audio_info.play.sample_rate * 4) ;		done = 0 ;		while (! done)		{	read_count = sf_read_short (sndfile, buffer, BUFFER_LEN) ;			if (read_count < BUFFER_LEN)			{	memset (&(buffer [read_count]), 0, (BUFFER_LEN - read_count) * sizeof (short)) ;				/* Tell the main application to terminate. */				done = SF_TRUE ;				} ;			start_count = 0 ;			output_count = BUFFER_LEN * sizeof (short) ;			while (output_count > 0)			{	/* write as much data as possible */				write_count = write (audio_fd, &(buffer [start_count]), output_count) ;				if (write_count > 0)				{	output_count -= write_count ;					start_count += write_count ;					}				else				{	/*	Give the audio output time to catch up. */					usleep (delay_time) ;					} ;				} ; /* while (outpur_count > 0) */			} ; /* while (! done) */		close (audio_fd) ;		} ;	return ;} /* solaris_play */#endif /* Solaris *//*==============================================================================**	Main function.*/intmain (int argc, char *argv []){	if (argc < 2)	{		printf ("\nUsage : %s <input sound file>\n\n", argv [0]) ;#if (OS_IS_WIN32 == 1)		printf ("This is a Unix style command line application which\n"				"should be run in a MSDOS box or Command Shell window.\n\n") ;		printf ("Sleeping for 5 seconds before exiting.\n\n") ;		/* This is the officially blessed by microsoft way but I can't get		** it to link.		**     Sleep (15) ;		** Instead, use this:		*/		_sleep (5 * 1000) ;#endif		return 1 ;		} ;#if defined (__linux__)	#if HAVE_ALSA_ASOUNDLIB_H		if (access ("/proc/asound/cards", R_OK) == 0)			alsa_play (argc, argv) ;		else	#endif		linux_play (argc, argv) ;#elif (defined (__MACH__) && defined (__APPLE__))	macosx_play (argc, argv) ;#elif (defined (sun) && defined (unix))	solaris_play (argc, argv) ;#elif (OS_IS_WIN32 == 1)	win32_play (argc, argv) ;#elif defined (__BEOS__)	printf ("This program cannot be compiled on BeOS.\n") ;	printf ("Instead, compile the file sfplay_beos.cpp.\n") ;	return 1 ;#else	puts ("*** Playing sound not yet supported on this platform.") ;	puts ("*** Please feel free to submit a patch.") ;	return 1 ;#endif	return 0 ;} /* main *//*** Do not edit or modify anything in this comment block.** The arch-tag line is a file identity tag for the GNU Arch** revision control system.**** arch-tag: 8fc4110d-6cec-4e03-91df-0f384cabedac*/

⌨️ 快捷键说明

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