Exemplo n.º 1
0
/* can be used as time stamp for interactive MIDI events */
INT64 XGetRealTimeSyncCount() {
    INT64 ret = g_checkpointSyncCount
	+ (XMicroseconds() - g_checkpointMicros)
	+ (HAE_GetSliceTimeInMicroseconds() * HAE_GetAudioBufferCount());
    return ret;
}
Exemplo n.º 2
0
// $$kk: 08.12.98 merge: changed this method to do convert to unsigned data if required by audio hardware 
void PV_AudioWaveOutFrameThread(void* context) {
    audio_info_t sunAudioHeader;
    char *pFillBuffer;
    INT32 count, currentPos, lastPos, sampleFrameSize;
    UINT32 startTime, stopTime, fillTime;
    int i;
    int rc;
    int bytesWritten;
    int bytesToWrite;


    ioctl(g_waveDevice, AUDIO_GETINFO, &sunAudioHeader);

    // calculate sample size for convertion of bytes to sample frames
    sampleFrameSize = 1;
		
    if (g_bitSize == 16) {
	sampleFrameSize *= 2;
    }

    if (g_channels == 2) {
	sampleFrameSize *= 2;
    }


    lastPos = sunAudioHeader.play.samples - ((g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK * 2) / sampleFrameSize);

    if (g_audioBufferBlock) {
	while ( (g_activeDoubleBuffer) && (g_shutDownDoubleBuffer == FALSE) ) {

	    /* put sync count and XMicroseconds into relation */
	    /* could be improved by using actual device sample count */
	    g_checkpointMicros = XMicroseconds();
	    g_checkpointSyncCount = GM_GetSyncTimeStamp();

	    // Generate HAE_SOLARIS_FRAMES_PER_BLOCK frames of audio
	    pFillBuffer = (char *)g_audioBufferBlock;	
	    for (count = 0; count < HAE_SOLARIS_FRAMES_PER_BLOCK; count++) {
				// Generate one frame audio
		HAE_BuildMixerSlice(context, pFillBuffer, g_audioByteBufferSize,
				    g_audioFramesToGenerate);

		pFillBuffer += g_audioByteBufferSize;

		if (g_shutDownDoubleBuffer) {
		    break;	// time to quit
		}
	    }

	    // $$kk
	    // for some solaris drivers, we must supply unsigned data when rendering 8 bit data
	    if (g_convertUnsigned && (g_bitSize == 8)) {
		pFillBuffer = (char *)g_audioBufferBlock;	
		for (i = 0; i < (g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK); i++) {
		    *pFillBuffer = (*pFillBuffer >= 0) ? (0x80 | *pFillBuffer) : (0x7F & *pFillBuffer);
		    pFillBuffer++;
		}
	    }
	
	    // $$jb: Changing the write() loop to handle cases when the 
	    // device is unavailable, or we can't write our entire buffer
	    bytesWritten = 0;
	    bytesToWrite = (g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK);
	    while( bytesToWrite > 0 )  {
		//$$fb don't write when it's time to quit.
		if( g_shutDownDoubleBuffer) {
		    break;
		}
		rc = write(g_waveDevice, ((char *)g_audioBufferBlock+bytesWritten), (size_t)bytesToWrite);
		if ( rc > 0 ) {
#ifdef USE_RAWDATA_CHECK
		    if (debugrawfile) {
			HAE_WriteFile(debugrawfile, ((char *)g_audioBufferBlock+bytesWritten), rc);
		    }
#endif
		    bytesWritten += rc;
		    bytesToWrite -= rc;
		} else {
                                // $$jb:  This happens when the device buffers cannot
                                // be written to.  Make sure we're not shutting down and 
                                // sleep a bit so that we don't completely hog the CPU
		    if( g_shutDownDoubleBuffer == FALSE ) {
			HAE_SleepFrameThread(context, HAE_SOLARIS_SOUND_PERIOD);
		    } else {
			break;
		    }
		} 
	    }


	    // O.k. We're done for now.
	    // Let the rest of the system know we're done ....

	    ioctl(g_waveDevice, AUDIO_GETINFO, &sunAudioHeader);
	    currentPos = sunAudioHeader.play.samples;

	    // $$jb: We have successfully written all our bytes.  
	    // If we encountered a problem while writing, play.error will be 1.
	    // This should be reset.
	    if( sunAudioHeader.play.error != 0 ) {
		AUDIO_INITINFO(&sunAudioHeader);
		sunAudioHeader.play.error = 0;
		ioctl(g_waveDevice, AUDIO_SETINFO, &sunAudioHeader);
	    }

			
	    // $$kk: 03.21.00: make sure we sleep at least once so that other threads can run.
	    // this is part of the fix for bug #4318062: "MixerSourceLine.drain hangs after
	    // repeated use."
	    //while ((currentPos < lastPos) && (g_shutDownDoubleBuffer == FALSE))
	    do {
		HAE_SleepFrameThread(context, HAE_SOLARIS_SOUND_PERIOD);		// in ms
				
		ioctl(g_waveDevice, AUDIO_GETINFO, &sunAudioHeader);
		currentPos = sunAudioHeader.play.samples;

                                // $$jb: Removing the bit of code that breaks out
                                // of this timing loop on sunAudioHeader.play.error != 0.
	    }
	    while ((currentPos < lastPos) &&
		   (lastPos - currentPos < (1 << 28)) && /* see note A */
		   (g_shutDownDoubleBuffer == FALSE));

	    // Note A: $$ay: Additional safeguard for wraparound of sample
	    // ------  count from 1 << 32 - 1.  Make sure the difference is
	    //         not a huge value
			
	    lastPos += (g_audioByteBufferSize * HAE_SOLARIS_FRAMES_PER_BLOCK) / sampleFrameSize;
	    // ... and reschedule ourselves.	
	}

	g_activeDoubleBuffer = FALSE;
    }
}
Exemplo n.º 3
0
// $$kk: 08.12.98 merge: changed this method to do convert to unsigned data if required by audio hardware
void PV_AudioWaveOutFrameThread(void* context)
{
    char			*pFillBuffer;
    long			count, currentPos, lastPos, sampleFrameSize;
    int				i;
    int rc;
    int bytesWritten;
    int bytesToWrite;
    //int avail;
    count_info audio_info;

    ioctl(g_waveDevice, SNDCTL_DSP_GETOPTR, &audio_info);

    // calculate sample size for convertion of bytes to sample frames
    sampleFrameSize = 1;

    if (g_bitSize == 16) {
        sampleFrameSize *= 2;
    }

    if (g_channels == 2) {
        sampleFrameSize *= 2;
    }

    // $$ay - sample count is in bytes for linux and not in samples
    lastPos = audio_info.bytes - ((g_audioByteBufferSize * HAE_LINUX_FRAMES_PER_BLOCK * 2));

    if (g_audioBufferBlock) {
        while ((g_activeDoubleBuffer) && (g_shutDownDoubleBuffer == FALSE)) {

            /* put sync count and XMicroseconds into relation */
            /* could be improved by using actual device sample count */
            g_checkpointMicros = XMicroseconds();
            g_checkpointSyncCount = GM_GetSyncTimeStamp();

            // Generate HAE_LINUX_FRAMES_PER_BLOCK frames of audio
            pFillBuffer = (char *)g_audioBufferBlock;
            for (count = 0; count < HAE_LINUX_FRAMES_PER_BLOCK; count++) {
                // Generate one frame audio
                HAE_BuildMixerSlice(context, pFillBuffer,
                                    g_audioByteBufferSize,
                                    g_audioFramesToGenerate);
                pFillBuffer += g_audioByteBufferSize;
                if (g_shutDownDoubleBuffer) {
                    break;	// time to quit
                }
            }

            // $$kk
            // for some solaris drivers, we must supply unsigned data when rendering 8 bit data
            if (g_convertUnsigned && (g_bitSize == 8)) {
                pFillBuffer = (char *)g_audioBufferBlock;
                for (i = 0; i < (g_audioByteBufferSize * HAE_LINUX_FRAMES_PER_BLOCK); i++) {
                    *pFillBuffer = (*pFillBuffer >= 0) ? (0x80 | *pFillBuffer) : (0x7F & *pFillBuffer);
                    pFillBuffer++;
                }
            }

            // $$jb: Changing the write() loop to handle cases when the
            // device is unavailable, or we can't write our entire buffer
            bytesWritten = 0;
            bytesToWrite = (g_audioByteBufferSize * HAE_LINUX_FRAMES_PER_BLOCK);

            while ( bytesToWrite > 0 ) {
#ifdef TODO
                // $$ay:  AARGH!!! Linux forces read to be non-blocking when opened for DUPLEX
                if (!g_openForCapture && g_supportsDuplex) {
                    int k, avail;

                    ioctl(g_waveDevice, SNDCTL_DSP_GETBLKSIZE, &avail);
                    k = read(g_waveDevice, dummyBuffer, avail);
                    //printf("AvailToRead = %d, Read = %d\n", avail, k);
                    //k = read(g_waveDevice, dummyBuffer, sizeof(dummyBuffer));
                    //printf("Read = %d\n", k);
                }
                ioctl(g_waveDevice, SNDCTL_DSP_GETBLKSIZE, &avail);
                if (bytesToWrite > avail)
                    rc = write(g_waveDevice, ((char *)g_audioBufferBlock+bytesWritten), avail);
                else
                    rc = write(g_waveDevice, ((char *)g_audioBufferBlock+bytesWritten), bytesToWrite);
                //printf("Wrote %d bytes\n", rc);
#endif

                //$$fb don't write when it's time to quit.
                if( g_shutDownDoubleBuffer) {
                    break;
                }
                rc = write(g_waveDevice, ((char *)g_audioBufferBlock+bytesWritten), bytesToWrite);
                if ( rc > 0 ) {
                    bytesWritten += rc;
                    bytesToWrite -= rc;
                } else {
                    // $$jb:  This happens when the device buffers cannot
                    // be written to.  Make sure we're not shutting down and
                    // sleep a bit so that we don't completely hog the CPU
                    if( g_shutDownDoubleBuffer == FALSE ) {
                        HAE_SleepFrameThread(context, HAE_LINUX_SOUND_PERIOD);
                    } else {
                        break;
                    }
                }
            }


            // O.k. We're done for now.
            // Let the rest of the system know we're done ....

            ioctl(g_waveDevice, SNDCTL_DSP_GETOPTR, &audio_info);
            currentPos = audio_info.bytes;
            // $$jb: We have successfully written all our bytes.
            // If we encountered a problem while writing, play.error will be 1.
            // This should be reset.

#ifdef TODO
            if ( sunAudioHeader.play.error != 0 ) {
                AUDIO_INITINFO(&sunAudioHeader);
                sunAudioHeader.play.error = 0;
                ioctl(g_waveDevice, AUDIO_SETINFO, &sunAudioHeader);
            }
#endif

            while ((currentPos < lastPos) && (g_shutDownDoubleBuffer == FALSE))	{
                HAE_SleepFrameThread(context, HAE_LINUX_SOUND_PERIOD);		// in ms

                ioctl(g_waveDevice, SNDCTL_DSP_GETOPTR, &audio_info);
                currentPos = audio_info.bytes;

                // $$jb: Removing the bit of code that breaks out
                // of this timing loop on sunAudioHeader.play.error != 0.
            }

            lastPos += (g_audioByteBufferSize * HAE_LINUX_FRAMES_PER_BLOCK);
            // ... and reschedule ourselves.
        }
        TRACE0("g_activeDoubleBuffer = FALSE;\n");
        g_activeDoubleBuffer = FALSE;
    }
}