Sophie

Sophie

distrib > Mandriva > 2009.1 > x86_64 > by-pkgid > 62a76a2ec8df084eca1536d575c0033e > files > 8

TiMidity++-2.13.2-26mdv2009.1.src.rpm

--- timidity/portaudio_a.c.neoclust	2004-05-18 05:59:34.000000000 +0200
+++ timidity/portaudio_a.c		2006-02-04 02:10:31.000000000 +0100
@@ -17,11 +17,13 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-    portaudio_a.c by Avatar <avatar@deva.net>
+    portaudio_a.c by skeishi <s_keishi@mutt.freemail.ne.jp>
     based on esd_a.c
 
     Functions to play sound through EsounD
 */
+#define PORTAUDIO_V19 1
+
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -63,8 +65,9 @@
 static int output_data(char *buf, int32 nbytes);
 static int acntl(int request, void *arg);
 
-static int framesPerBuffer=256;
+static int framesPerBuffer=128;
 static int stereo=2;
+static int conv16_32 =0;
 static int data_nbyte;
 static int numBuffers;
 static unsigned int framesPerInBuffer;
@@ -72,13 +75,22 @@
 //static int  firsttime;
 static int pa_active=0;
 static int first=1;
+
+#if PORTAUDIO_V19
+PaDeviceIndex DeviceIndex;
+const PaDeviceInfo *DeviceInfo;
+PaStreamParameters StreamParameters;
+PaStream *stream;
+PaError  err;
+#else
 PaDeviceID DeviceID;
 const PaDeviceInfo *DeviceInfo;
 PortAudioStream *stream;
 PaError  err;
+#endif
 typedef struct {
 	char buf[DATA_BLOCK_SIZE*2];
-	int32 samplesToGo;
+	uint32 samplesToGo;
 	char *bufpoint;
 	char *bufepoint;
 } padata_t;
@@ -93,7 +105,7 @@
 PlayMode portaudio_asio_play_mode = {
 	(SAMPLE_RATE),
     PE_16BIT|PE_SIGNED,
-    PF_PCM_STREAM|PF_BUFF_FRAGM_OPT/*|PF_CAN_TRACE*/,
+    PF_PCM_STREAM|PF_BUFF_FRAGM_OPT|PF_CAN_TRACE,
     -1,
     {32}, /* PF_BUFF_FRAGM_OPT  is need for TWSYNTH */
 	"PortAudio(ASIO)", 'o',
@@ -106,7 +118,7 @@
 PlayMode portaudio_win_ds_play_mode = {
 	(SAMPLE_RATE),
     PE_16BIT|PE_SIGNED,
-    PF_PCM_STREAM|PF_BUFF_FRAGM_OPT/*|PF_CAN_TRACE*/,
+    PF_PCM_STREAM|PF_BUFF_FRAGM_OPT|PF_CAN_TRACE,
     -1,
     {32}, /* PF_BUFF_FRAGM_OPT  is need for TWSYNTH */
 	"PortAudio(DirectSound)", 'P',
@@ -119,7 +131,7 @@
 PlayMode portaudio_win_wmme_play_mode = {
 	(SAMPLE_RATE),
     PE_16BIT|PE_SIGNED,
-    PF_PCM_STREAM|PF_BUFF_FRAGM_OPT/*|PF_CAN_TRACE*/,
+    PF_PCM_STREAM|PF_BUFF_FRAGM_OPT|PF_CAN_TRACE,
     -1,
     {32}, /* PF_BUFF_FRAGM_OPT  is need for TWSYNTH */
 	"PortAudio(WMME)", 'p',
@@ -139,7 +151,7 @@
 PlayMode dpm = {
 	(SAMPLE_RATE),
     PE_16BIT|PE_SIGNED,
-    PF_PCM_STREAM|PF_BUFF_FRAGM_OPT/*|PF_CAN_TRACE*/,
+    PF_PCM_STREAM|PF_BUFF_FRAGM_OPT|PF_CAN_TRACE,
     -1,
     {32}, /* PF_BUFF_FRAGM_OPT  is need for TWSYNTH */
 	"Portaudio Driver", 'p',
@@ -151,45 +163,90 @@
 };
 #endif
 
-
+#if PORTAUDIO_V19
+int paCallback(  const void *inputBuffer, void *outputBuffer,
+                     unsigned long framesPerBuffer,
+                     const PaStreamCallbackTimeInfo* timeInfo,
+                     PaStreamCallbackFlags statusFlags,
+	                 void *userData )
+#else
 int paCallback(  void *inputBuffer, void *outputBuffer,
-
                      unsigned long framesPerBuffer,
-
-                     PaTimestamp outTime, void *userData )
-
+                     PaTimestamp outTime, 
+                     void *userData )
+#endif
 {
 
     unsigned int i;
 	int finished = 0;
 
 /* Cast data passed through stream to our structure type. */
-
 //    pa_data_t pa_data = (pa_data_t*)userData;
-
     char *out = (char*)outputBuffer;
-	if(pa_data.samplesToGo < framesPerBuffer*data_nbyte*stereo  ){
-		for(i=0;i<pa_data.samplesToGo;i++){
-			*out++ = *(pa_data.bufpoint)++;
-			if( pa_data.buf+bytesPerInBuffer*2 <= pa_data.bufpoint ){
-				pa_data.bufpoint=pa_data.buf;
+	unsigned long datalength = framesPerBuffer*data_nbyte*stereo;
+	char * buflimit = pa_data.buf+bytesPerInBuffer*2;
+	
+	if(conv16_32){
+		if(pa_data.samplesToGo < datalength  ){		
+			for(i=0;i<pa_data.samplesToGo/2;i++){
+				*out++ = 0;
+				*out++ = 0;
+				*out++ = *(pa_data.bufpoint)++;
+				*out++ = *(pa_data.bufpoint)++;
+				if( buflimit <= pa_data.bufpoint ){
+					pa_data.bufpoint=pa_data.buf;
+				}
 			}
+			pa_data.samplesToGo=0;
+			for(;i<datalength/2;i++){
+				*out++ = 0;
+				*out++ = 0;
+				*out++ = 0;
+				*out++ = 0;
+			}
+			finished = 0;
+		}else{
+			for(i=0;i<datalength/2;i++){
+				*out++ = 0;
+				*out++ = 0;
+				*out++=*(pa_data.bufpoint)++;
+				*out++=*(pa_data.bufpoint)++;
+				if( buflimit <= pa_data.bufpoint ){
+					pa_data.bufpoint=pa_data.buf;
+				}
+			}
+			pa_data.samplesToGo -= datalength;
 		}
-		pa_data.samplesToGo=0;
-		for(;i<framesPerBuffer*data_nbyte*stereo;i++){
-			*out++=0;
-		}
-		finished = 0;
 	}else{
-		for(i=0;i<framesPerBuffer*data_nbyte*stereo;i++){
-			*out++=*(pa_data.bufpoint)++;
-			if( pa_data.buf+bytesPerInBuffer*2 <= pa_data.bufpoint ){
-				pa_data.bufpoint=pa_data.buf;
+		if(pa_data.samplesToGo < datalength  ){
+			if(pa_data.bufpoint+datalength <= buflimit){
+				memcpy(out, pa_data.bufpoint, datalength);
+				pa_data.bufpoint += datalength;
+			}else{
+				int32 send;
+				send = buflimit-pa_data.bufpoint;
+				memcpy(out, pa_data.bufpoint, send);
+				out +=send;
+				memcpy(out, pa_data.buf, datalength -send);
+				pa_data.bufpoint = pa_data.buf+datalength -send;
+			}
+			memset(out, 0x0, datalength-pa_data.samplesToGo);
+			finished = 0;
+		}else{
+			if(pa_data.bufpoint + datalength <= buflimit){
+				memcpy(out, pa_data.bufpoint, datalength);
+				pa_data.bufpoint += datalength;
+			}else{
+				int32 send;
+				send = buflimit-pa_data.bufpoint;
+				memcpy(out, pa_data.bufpoint, send);
+				out += send;
+				memcpy(out, pa_data.buf, datalength -send);
+				pa_data.bufpoint = pa_data.buf+datalength -send;
 			}
+			pa_data.samplesToGo -= datalength;
 		}
-		pa_data.samplesToGo -= framesPerBuffer*data_nbyte*stereo;
 	}
-
     return finished ;
 
 }
@@ -234,16 +291,83 @@
 		}
   }
 #endif
+	/* if call twice Pa_OpenStream causes paDeviceUnavailable error  */
+	if(pa_active == 1) return 0; 
 	if(pa_active == 0){
 		err = Pa_Initialize();
 		if( err != paNoError ) goto error;
 		pa_active = 1;
 	}
-	if(first == 1){
-		atexit(close_output);
-		first = 0;
+
+#ifdef PORTAUDIO_V19
+	DeviceIndex = Pa_GetDefaultOutputDevice();
+	if(DeviceIndex==paNoDevice) goto error;
+	DeviceInfo = Pa_GetDeviceInfo( DeviceIndex);
+	if(DeviceInfo==NULL) goto error;
+
+	if (dpm.encoding & PE_24BIT) {
+		SampleFormat = paInt24;
+	}else if (dpm.encoding & PE_16BIT) {
+		SampleFormat = paInt16;
+	}else {
+		SampleFormat = paInt8;
 	}
 
+	stereo = (dpm.encoding & PE_MONO) ? 1 : 2;
+	data_nbyte = (dpm.encoding & PE_16BIT) ? 2 : 1;
+	data_nbyte = (dpm.encoding & PE_24BIT) ? 3 : data_nbyte;
+	
+	pa_data.samplesToGo = 0;
+	pa_data.bufpoint = pa_data.buf;
+	pa_data.bufepoint = pa_data.buf;
+//	firsttime = 1;
+	numBuffers = 1; //Pa_GetMinNumBuffers( framesPerBuffer, dpm.rate );
+	framesPerInBuffer = numBuffers * framesPerBuffer;
+	if (framesPerInBuffer < 4096) framesPerInBuffer = 4096;
+	bytesPerInBuffer = framesPerInBuffer * data_nbyte * stereo;
+
+	/* set StreamParameters */
+	StreamParameters.device = DeviceIndex;
+	StreamParameters.channelCount = stereo;
+	if(ctl->id_character != 'r' && ctl->id_character != 'A' && ctl->id_character != 'W' && ctl->id_character != 'P'){
+		StreamParameters.suggestedLatency = DeviceInfo->defaultHighOutputLatency;
+	}else{
+		StreamParameters.suggestedLatency = DeviceInfo->defaultLowOutputLatency;
+	}
+	StreamParameters.hostApiSpecificStreamInfo = NULL;
+	
+	if( SampleFormat == paInt16){
+		StreamParameters.sampleFormat = paInt16;
+		if( paFormatIsSupported != Pa_IsFormatSupported( NULL , 
+							&StreamParameters,(double) dpm.rate )){
+			StreamParameters.sampleFormat = paInt32;
+			conv16_32 = 1;
+		} else {
+			StreamParameters.sampleFormat = paInt16;
+			conv16_32 = 0;
+		}
+	}else{
+		StreamParameters.sampleFormat = SampleFormat;
+	}
+	err = Pa_IsFormatSupported( NULL ,
+                             &StreamParameters,
+							(double) dpm.rate );
+	if ( err != paNoError) goto error;
+	err = Pa_OpenStream(    
+		& stream,			/* passes back stream pointer */
+		NULL,			 	/* inputStreamParameters */
+		&StreamParameters,	/* outputStreamParameters */
+		(double) dpm.rate,	/* sample rate */
+		paFramesPerBufferUnspecified,	/* frames per buffer */
+		paFramesPerBufferUnspecified,	/* PaStreamFlags */
+		paCallback,			/* specify our custom callback */
+		&pa_data			/* pass our data through to callback */
+		);
+//		Pa_Sleeep(1);
+	if ( err != paNoError) goto error;
+	return 0;
+	
+#else
 	DeviceID = Pa_GetDefaultOutputDeviceID();
 	if(DeviceID==paNoDevice) goto error;
 	DeviceInfo = Pa_GetDeviceInfo( DeviceID);	
@@ -252,13 +376,21 @@
 
 	exclude_enc = PE_ULAW | PE_ALAW | PE_BYTESWAP;
 	include_enc = PE_SIGNED;
-	if (!(nativeSampleFormats & paInt16)) {exclude_enc |= PE_16BIT;}
+	if (!(nativeSampleFormats & paInt16) && !(nativeSampleFormats & paInt32)) {exclude_enc |= PE_16BIT;}
 	if (!(nativeSampleFormats & paInt24)) {exclude_enc |= PE_24BIT;}
     dpm.encoding = validate_encoding(dpm.encoding, include_enc, exclude_enc);
 
-	if (dpm.encoding & PE_24BIT) {SampleFormat = paInt24;}
-	else if (dpm.encoding & PE_16BIT) {SampleFormat = paInt16;}
-	else {SampleFormat = paInt8;}
+	if (dpm.encoding & PE_24BIT) {
+		SampleFormat = paInt24;
+	}else if (dpm.encoding & PE_16BIT) {
+		if(nativeSampleFormats & paInt16) SampleFormat = paInt16;
+		else{
+			SampleFormat = paInt32;
+			conv16_32 = 1;
+		}
+	}else {
+		SampleFormat = paInt8;
+	}
 
 	stereo = (dpm.encoding & PE_MONO) ? 1 : 2;
 	data_nbyte = (dpm.encoding & PE_16BIT) ? 2 : 1;
@@ -300,6 +432,8 @@
 	if ( err != paNoError && err != paHostError) goto error;
 	return 0;
 
+#endif
+
 error:
 	Pa_Terminate(); pa_active = 0;
 #ifdef AU_PORTAUDIO_DLL
@@ -316,11 +450,17 @@
 //	if(pa_data.samplesToGo > DATA_BLOCK_SIZE){ 
 //		Sleep(  (pa_data.samplesToGo - DATA_BLOCK_SIZE)/dpm.rate/4  );
 //	}
-	for(i=0;i<nbytes;i++){
-		*(pa_data.bufepoint)++ = *buf++ ;
-		if( pa_data.buf+bytesPerInBuffer*2 <= pa_data.bufepoint ){
-			pa_data.bufepoint=pa_data.buf;
-		}
+	if (pa_data.buf+bytesPerInBuffer*2 >= pa_data.bufepoint + nbytes){
+		memcpy(pa_data.bufepoint, buf, nbytes);
+		pa_data.bufepoint += nbytes;
+		//buf += nbytes;
+	}else{
+		int32 send = pa_data.buf+bytesPerInBuffer*2 - pa_data.bufepoint;
+		memcpy(pa_data.bufepoint, buf, send);
+		buf += send;
+		memcpy(pa_data.buf, buf, nbytes - send);
+		pa_data.bufepoint = pa_data.buf + nbytes - send;
+		//buf += nbytes-send;
 	}
 	pa_data.samplesToGo += nbytes;
 
@@ -332,12 +472,18 @@
 		firsttime=0;
 	}
 */
+#if PORTAUDIO_V19
+	if( 0==Pa_IsStreamActive(stream)){
+#else
 	if( 0==Pa_StreamActive(stream)){
+#endif
 		err = Pa_StartStream( stream );
 
 		if( err != paNoError ) goto error;
 	}
-    while(pa_data.samplesToGo > bytesPerInBuffer){ Pa_Sleep(1);};
+		
+	if(ctl->id_character != 'r' && ctl->id_character != 'A' && ctl->id_character != 'W' && ctl->id_character != 'P')
+	    while((pa_active==1) && (pa_data.samplesToGo > bytesPerInBuffer)){ Pa_Sleep(1);};
 //	Pa_Sleep( (pa_data.samplesToGo - bytesPerInBuffer)/dpm.rate * 1000);
 	return 0;
 
@@ -350,7 +496,11 @@
 static void close_output(void)
 {	
 	if( pa_active==0) return;
+#if PORTAUDIO_V19
+	if(Pa_IsStreamActive(stream)){
+#else
 	if(Pa_StreamActive(stream)){
+#endif
 		Pa_Sleep(  bytesPerInBuffer/dpm.rate*1000  );
 	}	
 	err = Pa_StopStream( stream );
@@ -382,26 +532,26 @@
       case PM_REQ_GETQSIZ:
 		 *(int *)arg = bytesPerInBuffer*2;
     	return 0;
-		break;
+		//break;
       case PM_REQ_GETFILLABLE:
 		 *(int *)arg = bytesPerInBuffer*2-pa_data.samplesToGo;
     	return 0;
-		break;
+		//break;
       case PM_REQ_GETFILLED:
 		 *(int *)arg = pa_data.samplesToGo;
     	return 0;
-		break;
+		//break;
       case PM_REQ_DISCARD:
     	Pa_StopStream( stream );
     	close_output();
 	    open_output();
 		return 0;
-		break;
+		//break;
       case PM_REQ_FLUSH:
     	close_output();
 	    open_output();
 		return 0;
-		break;
+		//break;
       case PM_REQ_RATE:  /* NOT WORK */
     	{
     		int i;
@@ -418,7 +568,7 @@
     			return -1;
     		}
     	}
-    	break;
+    	//break;
     }
     return -1;
 }