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

📄 sdl_dx5audio.c

📁 网络MPEG4IP流媒体开发源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return(NULL);	}	cursor /= mixlen;	playing = cursor;	cursor = (cursor+1)%NUM_BUFFERS;	cursor *= mixlen;	/* Lock the audio buffer */	result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);	if ( result == DSERR_BUFFERLOST ) {		IDirectSoundBuffer_Restore(mixbuf);		result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,				(LPVOID *)&locked_buf, &rawlen, NULL, &junk, 0);	}	if ( result != DS_OK ) {		SetDSerror("DirectSound Lock", result);		return(NULL);	}	return(locked_buf);}static void DX5_WaitDone(_THIS){	Uint8 *stream;	/* Wait for the playing chunk to finish */	stream = this->GetAudioBuf(this);	if ( stream != NULL ) {		memset(stream, silence, mixlen);		this->PlayAudio(this);	}	this->WaitAudio(this);	/* Stop the looping sound buffer */	IDirectSoundBuffer_Stop(mixbuf);}static void DX5_CloseAudio(_THIS){	if ( sound != NULL ) {		if ( mixbuf != NULL ) {			/* Clean up the audio buffer */			IDirectSoundBuffer_Release(mixbuf);			mixbuf = NULL;		}		if ( audio_event != NULL ) {			CloseHandle(audio_event);			audio_event = NULL;		}		IDirectSound_Release(sound);		sound = NULL;	}}#ifdef USE_PRIMARY_BUFFER/* This function tries to create a primary audio buffer, and returns the   number of audio chunks available in the created buffer.*/static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, 	LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize){	HRESULT result;	DSBUFFERDESC format;	DSBCAPS caps;	int numchunks;	/* Try to set primary mixing privileges */	result = IDirectSound_SetCooperativeLevel(sndObj, focus,							DSSCL_WRITEPRIMARY);	if ( result != DS_OK ) {#ifdef DEBUG_SOUND		SetDSerror("DirectSound SetCooperativeLevel", result);#endif		return(-1);	}	/* Try to create the primary buffer */	memset(&format, 0, sizeof(format));	format.dwSize = sizeof(format);	format.dwFlags=(DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2);	format.dwFlags |= DSBCAPS_STICKYFOCUS;#ifdef USE_POSITION_NOTIFY	format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;#endif	result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);	if ( result != DS_OK ) {#ifdef DEBUG_SOUND		SetDSerror("DirectSound CreateSoundBuffer", result);#endif		return(-1);	}	/* Check the size of the fragment buffer */	memset(&caps, 0, sizeof(caps));	caps.dwSize = sizeof(caps);	result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps);	if ( result != DS_OK ) {#ifdef DEBUG_SOUND		SetDSerror("DirectSound GetCaps", result);#endif		IDirectSoundBuffer_Release(*sndbuf);		return(-1);	}	if ( (chunksize > caps.dwBufferBytes) ||				((caps.dwBufferBytes%chunksize) != 0) ) {		/* The primary buffer size is not a multiple of 'chunksize'		   -- this hopefully doesn't happen when 'chunksize' is a 		      power of 2.		*/		IDirectSoundBuffer_Release(*sndbuf);		SDL_SetError("Primary buffer size is: %d, cannot break it into chunks of %d bytes\n",					caps.dwBufferBytes, chunksize);		return(-1);	}	numchunks = (caps.dwBufferBytes/chunksize);	/* Set the primary audio format */	result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);	if ( result != DS_OK ) {#ifdef DEBUG_SOUND		SetDSerror("DirectSound SetFormat", result);#endif		IDirectSoundBuffer_Release(*sndbuf);		return(-1);	}	return(numchunks);}#endif /* USE_PRIMARY_BUFFER *//* This function tries to create a secondary audio buffer, and returns the   number of audio chunks available in the created buffer.*/static int CreateSecondary(LPDIRECTSOUND sndObj, HWND focus,	LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize){	const int numchunks = 2;	HRESULT result;	DSBUFFERDESC format;	LPVOID pvAudioPtr1, pvAudioPtr2;	DWORD  dwAudioBytes1, dwAudioBytes2;	/* Try to set primary mixing privileges */	if ( focus ) {		result = IDirectSound_SetCooperativeLevel(sndObj,					focus, DSSCL_PRIORITY);	} else {		result = IDirectSound_SetCooperativeLevel(sndObj,					GetDesktopWindow(), DSSCL_NORMAL);	}	if ( result != DS_OK ) {#ifdef DEBUG_SOUND		SetDSerror("DirectSound SetCooperativeLevel", result);#endif		return(-1);	}	/* Try to create the secondary buffer */	memset(&format, 0, sizeof(format));	format.dwSize = sizeof(format);	format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;#ifdef USE_POSITION_NOTIFY	format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;#endif	if ( ! focus ) {		format.dwFlags |= DSBCAPS_GLOBALFOCUS;	} else {		format.dwFlags |= DSBCAPS_STICKYFOCUS;	}	format.dwBufferBytes = numchunks*chunksize;	if ( (format.dwBufferBytes < DSBSIZE_MIN) ||	     (format.dwBufferBytes > DSBSIZE_MAX) ) {		SDL_SetError("Sound buffer size must be between %d and %d",				DSBSIZE_MIN/numchunks, DSBSIZE_MAX/numchunks);		return(-1);	}	format.dwReserved = 0;	format.lpwfxFormat = wavefmt;	result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);	if ( result != DS_OK ) {		SetDSerror("DirectSound CreateSoundBuffer", result);		return(-1);	}	IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);	/* Silence the initial audio buffer */	result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,	                                 (LPVOID *)&pvAudioPtr1, &dwAudioBytes1,	                                 (LPVOID *)&pvAudioPtr2, &dwAudioBytes2,	                                 DSBLOCK_ENTIREBUFFER);	if ( result == DS_OK ) {		if ( wavefmt->wBitsPerSample == 8 ) {			memset(pvAudioPtr1, 0x80, dwAudioBytes1);		} else {			memset(pvAudioPtr1, 0x00, dwAudioBytes1);		}		IDirectSoundBuffer_Unlock(*sndbuf,		                          (LPVOID)pvAudioPtr1, dwAudioBytes1,		                          (LPVOID)pvAudioPtr2, dwAudioBytes2);	}	/* We're ready to go */	return(numchunks);}/* This function tries to set position notify events on the mixing buffer */#ifdef USE_POSITION_NOTIFYstatic int CreateAudioEvent(_THIS){	LPDIRECTSOUNDNOTIFY notify;	DSBPOSITIONNOTIFY *notify_positions;	int i, retval;	HRESULT result;	/* Default to fail on exit */	retval = -1;	notify = NULL;	/* Query for the interface */	result = IDirectSoundBuffer_QueryInterface(mixbuf,			&IID_IDirectSoundNotify, (void *)&notify);	if ( result != DS_OK ) {		goto done;	}	/* Allocate the notify structures */	notify_positions = (DSBPOSITIONNOTIFY *)malloc(NUM_BUFFERS*					sizeof(*notify_positions));	if ( notify_positions == NULL ) {		goto done;	}	/* Create the notify event */	audio_event = CreateEvent(NULL, FALSE, FALSE, NULL);	if ( audio_event == NULL ) {		goto done;	}	/* Set up the notify structures */	for ( i=0; i<NUM_BUFFERS; ++i ) {		notify_positions[i].dwOffset = i*mixlen;		notify_positions[i].hEventNotify = audio_event;	}	result = IDirectSoundNotify_SetNotificationPositions(notify,					NUM_BUFFERS, notify_positions);	if ( result == DS_OK ) {		retval = 0;	}done:	if ( notify != NULL ) {		IDirectSoundNotify_Release(notify);	}	return(retval);}#endif /* USE_POSITION_NOTIFY */static int DX5_OpenAudio(_THIS, SDL_AudioSpec *spec){	HRESULT      result;	WAVEFORMATEX waveformat;	/* Set basic WAVE format parameters */	memset(&waveformat, 0, sizeof(waveformat));	waveformat.wFormatTag = WAVE_FORMAT_PCM;	/* Determine the audio parameters from the AudioSpec */	switch ( spec->format & 0xFF ) {		case 8:			/* Unsigned 8 bit audio data */			spec->format = AUDIO_U8;			silence = 0x80;			waveformat.wBitsPerSample = 8;			break;		case 16:			/* Signed 16 bit audio data */			spec->format = AUDIO_S16;			silence = 0x00;			waveformat.wBitsPerSample = 16;			break;		default:			SDL_SetError("Unsupported audio format");			return(-1);	}	waveformat.nChannels = spec->channels;	waveformat.nSamplesPerSec = spec->freq;	waveformat.nBlockAlign =		waveformat.nChannels * (waveformat.wBitsPerSample/8);	waveformat.nAvgBytesPerSec = 		waveformat.nSamplesPerSec * waveformat.nBlockAlign;	/* Update the fragment size as size in bytes */	SDL_CalculateAudioSpec(spec);	/* Open the audio device */	result = DSoundCreate(NULL, &sound, NULL);	if ( result != DS_OK ) {		SetDSerror("DirectSoundCreate", result);		return(-1);	}	/* Create the audio buffer to which we write */	NUM_BUFFERS = -1;#ifdef USE_PRIMARY_BUFFER	if ( mainwin ) {		NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf,						&waveformat, spec->size);	}#endif /* USE_PRIMARY_BUFFER */	if ( NUM_BUFFERS < 0 ) {		NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf,						&waveformat, spec->size);		if ( NUM_BUFFERS < 0 ) {			return(-1);		}#ifdef DEBUG_SOUND		fprintf(stderr, "Using secondary audio buffer\n");#endif	}#ifdef DEBUG_SOUND	else		fprintf(stderr, "Using primary audio buffer\n");#endif	/* The buffer will auto-start playing in DX5_WaitAudio() */	playing = 0;	mixlen = spec->size;#ifdef USE_POSITION_NOTIFY	/* See if we can use DirectX 6 event notification */	if ( CreateAudioEvent(this) == 0 ) {		this->WaitAudio = DX6_WaitAudio_EventWait;	} else {		this->WaitAudio = DX5_WaitAudio_BusyWait;	}#endif	return(0);}static int DX5_AudioDelayMsec (_THIS){      DWORD cursor, write;      HRESULT result;      int odelay;      /* char buffer[80]; */      result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &cursor, &write);+       write = cursor / mixlen;      write = (write+1)%NUM_BUFFERS;      write *= mixlen;      if (result == DS_OK) {	/* 	 * delay in msec is bytes  * 1000 / (bytes per sample * channels * freq)+        */	odelay = (write - cursor);	odelay *= 1000;	odelay /= this->spec.channels;	if (!(this->spec.format == AUDIO_U8 ||	      this->spec.format == AUDIO_S8)) {	  odelay /= 2; // 2 bytes per sample	}	odelay /= this->spec.freq;	return odelay;      }      return -1;}

⌨️ 快捷键说明

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