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

📄 ao_dsound.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 2 页
字号:
	  // Lock the buffer  res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);   // If the buffer was lost, restore and retry lock.   if (DSERR_BUFFERLOST == res)   {     IDirectSoundBuffer_Restore(hdsbuf);	res = IDirectSoundBuffer_Lock(hdsbuf,write_offset, len, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0);  }     if (SUCCEEDED(res))   {  	if( (ao_data.channels == 6) && (ao_data.format!=AF_FORMAT_AC3) ) {  	    // reorder channels while writing to pointers.  	    // it's this easy because buffer size and len are always  	    // aligned to multiples of channels*bytespersample  	    // there's probably some room for speed improvements here  	    const int chantable[6] = {0, 1, 4, 5, 2, 3}; // reorder "matrix"  	    int i, j;  	    int numsamp,sampsize;  	    sampsize = af_fmt2bits(ao_data.format)>>3; // bytes per sample  	    numsamp = dwBytes1 / (ao_data.channels * sampsize);  // number of samples for each channel in this buffer  	    for( i = 0; i < numsamp; i++ ) for( j = 0; j < ao_data.channels; j++ ) {  	        memcpy(lpvPtr1+(i*ao_data.channels*sampsize)+(chantable[j]*sampsize),data+(i*ao_data.channels*sampsize)+(j*sampsize),sampsize);  	    }  	    if (NULL != lpvPtr2 )  	    {  	        numsamp = dwBytes2 / (ao_data.channels * sampsize);  	        for( i = 0; i < numsamp; i++ ) for( j = 0; j < ao_data.channels; j++ ) {  	            memcpy(lpvPtr2+(i*ao_data.channels*sampsize)+(chantable[j]*sampsize),data+dwBytes1+(i*ao_data.channels*sampsize)+(j*sampsize),sampsize);  	        }  	    }  	    write_offset+=dwBytes1+dwBytes2;  	    if(write_offset>=buffer_size)write_offset=dwBytes2;  	} else {  	    // Write to pointers without reordering. 	memcpy(lpvPtr1,data,dwBytes1);    if (NULL != lpvPtr2 )memcpy(lpvPtr2,data+dwBytes1,dwBytes2);	write_offset+=dwBytes1+dwBytes2;    if(write_offset>=buffer_size)write_offset=dwBytes2;  	}	   // Release the data back to DirectSound.     res = IDirectSoundBuffer_Unlock(hdsbuf,lpvPtr1,dwBytes1,lpvPtr2,dwBytes2);    if (SUCCEEDED(res))     { 	  // Success. 	  DWORD status;	  IDirectSoundBuffer_GetStatus(hdsbuf, &status);      if (!(status & DSBSTATUS_PLAYING)){	    res = IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);	  }	  return dwBytes1+dwBytes2;     }   }   // Lock, Unlock, or Restore failed.   return 0;}/***************************************************************************************//**\brief handle control commands\param cmd command\param arg argument\return CONTROL_OK or -1 in case the command can't be handled*/static int control(int cmd, void *arg){	DWORD volume;	switch (cmd) {		case AOCONTROL_GET_VOLUME: {			ao_control_vol_t* vol = (ao_control_vol_t*)arg;			IDirectSoundBuffer_GetVolume(hdsbuf, &volume);			vol->left = vol->right = (float)(volume+10000) / 100.0;			//printf("ao_dsound: volume: %f\n",vol->left);			return CONTROL_OK;		}		case AOCONTROL_SET_VOLUME: {			ao_control_vol_t* vol = (ao_control_vol_t*)arg;			volume = (vol->right * 100.0)-10000;			IDirectSoundBuffer_SetVolume(hdsbuf, volume);			//printf("ao_dsound: volume: %f\n",vol->left);			return CONTROL_OK;		}	}	return -1;}/** \brief setup sound device\param rate samplerate\param channels number of channels\param format format\param flags unused\return 1=success 0=fail*/static int init(int rate, int channels, int format, int flags){    int res;	if (!InitDirectSound()) return 0;	// ok, now create the buffers	WAVEFORMATEXTENSIBLE wformat;	DSBUFFERDESC dsbpridesc;	DSBUFFERDESC dsbdesc;	//check if the format is supported in general	switch(format){		case AF_FORMAT_AC3:		case AF_FORMAT_S24_LE:		case AF_FORMAT_S16_LE:		case AF_FORMAT_S8:			break;		default:			mp_msg(MSGT_AO, MSGL_V,"ao_dsound: format %s not supported defaulting to Signed 16-bit Little-Endian\n",af_fmt2str_short(format));			format=AF_FORMAT_S16_LE;	}   		//fill global ao_data	ao_data.channels = channels;	ao_data.samplerate = rate;	ao_data.format = format;	ao_data.bps = channels * rate * (af_fmt2bits(format)>>3);	if(ao_data.buffersize==-1) ao_data.buffersize = ao_data.bps; // space for 1 sec	mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Samplerate:%iHz Channels:%i Format:%s\n", rate, channels, af_fmt2str_short(format));	mp_msg(MSGT_AO, MSGL_V,"ao_dsound: Buffersize:%d bytes (%d msec)\n", ao_data.buffersize, ao_data.buffersize / ao_data.bps * 1000);	//fill waveformatex	ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE));	wformat.Format.cbSize          = (channels > 2) ? sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) : 0;	wformat.Format.nChannels       = channels;	wformat.Format.nSamplesPerSec  = rate;	if (format == AF_FORMAT_AC3) {		wformat.Format.wFormatTag      = WAVE_FORMAT_DOLBY_AC3_SPDIF;		wformat.Format.wBitsPerSample  = 16;		wformat.Format.nBlockAlign     = 4;	} else {		wformat.Format.wFormatTag      = (channels > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;		wformat.Format.wBitsPerSample  = af_fmt2bits(format);		wformat.Format.nBlockAlign     = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3);	}	// fill in primary sound buffer descriptor	memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC));	dsbpridesc.dwSize = sizeof(DSBUFFERDESC);	dsbpridesc.dwFlags       = DSBCAPS_PRIMARYBUFFER;	dsbpridesc.dwBufferBytes = 0;	dsbpridesc.lpwfxFormat   = NULL;	// fill in the secondary sound buffer (=stream buffer) descriptor	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));	dsbdesc.dwSize = sizeof(DSBUFFERDESC);	dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */	                | DSBCAPS_GLOBALFOCUS         /** Allows background playing */	                | DSBCAPS_CTRLVOLUME;         /** volume control enabled */	if (channels > 2) {		wformat.dwChannelMask = channel_mask[channels - 3];		wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;		wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample;		// Needed for 5.1 on emu101k - shit soundblaster		dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;	}	wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign;	dsbdesc.dwBufferBytes = ao_data.buffersize;	dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat;	buffer_size = dsbdesc.dwBufferBytes;	write_offset = 0;	min_free_space = wformat.Format.nBlockAlign;	ao_data.outburst = wformat.Format.nBlockAlign * 512;	// create primary buffer and set its format    	res = IDirectSound_CreateSoundBuffer( hds, &dsbpridesc, &hdspribuf, NULL );	if ( res != DS_OK ) {		UninitDirectSound();		mp_msg(MSGT_AO, MSGL_ERR,"ao_dsound: cannot create primary buffer (%s)\n", dserr2str(res));		return 0;	}	res = IDirectSoundBuffer_SetFormat( hdspribuf, (WAVEFORMATEX *)&wformat );	if ( res != DS_OK ) mp_msg(MSGT_AO, MSGL_WARN,"ao_dsound: cannot set primary buffer format (%s), using standard setting (bad quality)", dserr2str(res));	mp_msg(MSGT_AO, MSGL_V, "ao_dsound: primary buffer created\n");	// now create the stream buffer	res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);	if (res != DS_OK) {		if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) {			// Try without DSBCAPS_LOCHARDWARE			dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;			res = IDirectSound_CreateSoundBuffer(hds, &dsbdesc, &hdsbuf, NULL);		}		if (res != DS_OK) {			UninitDirectSound();			mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: cannot create secondary (stream)buffer (%s)\n", dserr2str(res));			return 0;		}	}	mp_msg(MSGT_AO, MSGL_V, "ao_dsound: secondary (stream)buffer created\n");	return 1;}/**\brief stop playing and empty buffers (for seeking/pause)*/static void reset(){	IDirectSoundBuffer_Stop(hdsbuf);	// reset directsound buffer	IDirectSoundBuffer_SetCurrentPosition(hdsbuf, 0);	write_offset=0;}/**\brief stop playing, keep buffers (for pause)*/static void audio_pause(){	IDirectSoundBuffer_Stop(hdsbuf);}/**\brief resume playing, after audio_pause()*/static void audio_resume(){	IDirectSoundBuffer_Play(hdsbuf, 0, 0, DSBPLAY_LOOPING);}/** \brief close audio device\param immed stop playback immediately*/static void uninit(int immed){	if(immed)reset();	else{		DWORD status;		IDirectSoundBuffer_Play(hdsbuf, 0, 0, 0);		while(!IDirectSoundBuffer_GetStatus(hdsbuf,&status) && (status&DSBSTATUS_PLAYING))			usec_sleep(20000);	}	DestroyBuffer();	UninitDirectSound();}/**\brief find out how many bytes can be written into the audio buffer without\return free space in bytes, has to return 0 if the buffer is almost full*/static int get_space(){	int space;	DWORD play_offset;	IDirectSoundBuffer_GetCurrentPosition(hdsbuf,&play_offset,NULL);	space=buffer_size-(write_offset-play_offset);                                             	//                |                                                      | <-- const --> |                |                 |	//                buffer start                                           play_cursor     write_cursor     write_offset      buffer end	// play_cursor is the actual postion of the play cursor	// write_cursor is the position after which it is assumed to be save to write data	// write_offset is the postion where we actually write the data to	if(space > buffer_size)space -= buffer_size; // write_offset < play_offset	if(space < min_free_space)return 0;	return space-min_free_space;}/**\brief play 'len' bytes of 'data'\param data pointer to the data to play\param len size in bytes of the data buffer, gets rounded down to outburst*n\param flags currently unused\return number of played bytes*/static int play(void* data, int len, int flags){	DWORD play_offset;	int space;  	// make sure we have enough space to write data	IDirectSoundBuffer_GetCurrentPosition(hdsbuf,&play_offset,NULL);	space=buffer_size-(write_offset-play_offset);                                             	if(space > buffer_size)space -= buffer_size; // write_offset < play_offset	if(space < len) len = space;	len = (len / ao_data.outburst) * ao_data.outburst;	return write_buffer(data, len);}/**\brief get the delay between the first and last sample in the buffer\return delay in seconds*/static float get_delay(){	DWORD play_offset;	int space;	IDirectSoundBuffer_GetCurrentPosition(hdsbuf,&play_offset,NULL);	space=play_offset-write_offset;                                             	if(space <= 0)space += buffer_size;	return (float)(buffer_size - space) / (float)ao_data.bps;}

⌨️ 快捷键说明

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