// called by the irq function in the hardware object when we get an interrupt // first call _vUpdateProcessed() to update the dma amd audio buffer related // stuff. Next if we have buffers on the primary queue try to read/write them // to the audiobuffer. Look at the buffers on the done queue and see if they // can be returned and finally process any events pending. void WAVESTREAM::Process(void) { PSTREAMBUFFER ptemp; ULONG ulCurBytesProcessed = 0; ULONG bytesinc; switch (ulStreamType & STREAM_WRITE) { case STREAM_WRITE: { OSS16_StreamGetPos(this, &ulCurBytesProcessed); if(ulCurBytesProcessed == 0) { //shouldn't happen DebugInt3(); return; } bytesinc = ulCurBytesProcessed - _ulBytesProcessed; dprintf4(("Process: %lx %x", ulCurBytesProcessed, (USHORT)bytesinc)); if(ulCurBytesProcessed < _ulBytesProcessed) { dprintf(("WARNING: Process: Current pos %ld incr %d", ulCurBytesProcessed, (USHORT)bytesinc)); } _ulBytesProcessed = ulCurBytesProcessed; while(bytesinc) { if(qhDone.IsElements()) { // if there are buffers that have been // completly written to the audio buffer // check the first one on the done queue // if it's data has been consumed by // the hardware return it ptemp = (PSTREAMBUFFER)qhDone.Head(); ptemp->ulDonepos += bytesinc; bytesinc = 0; if(ptemp->ulDonepos >= ptemp->ulBuffsz) { //calc position in next buffer bytesinc = ptemp->ulDonepos - ptemp->ulBuffsz; dprintf3(("Process: Return buffer %lx size %d", ptemp->pBuffptr, ptemp->ulBuffsz)); ReturnBuffer(); } } else break; //shouldn't happen } AddBuffers(FALSE); break; } case STREAM_READ: while(_vReadAudioBuf()); break; default: break; } /* endswitch */ ProcessEvents(); }
ULONG WAVESTREAM::Write(PSTREAMBUFFER pStreamBuf) { qhInProcess.PushOnTail((PQUEUEELEMENT)pStreamBuf); dprintf2(("WAVESTREAM::Write: Push on tail %lx %ld", ((PSTREAMBUFFER)qhInProcess.Tail())->pBuffptr, ((PSTREAMBUFFER)qhInProcess.Tail())->ulBuffsz)); if(fUnderrun) { fUnderrun = FALSE; OSS16_StreamReset(this); AddBuffers(TRUE); if(ulStreamType == STREAM_WAVE_PLAY) OSS16_SetWaveOutVol(this, volume); } return 0; }
ULONG WAVESTREAM::StartStream(void) { PSTREAMBUFFER pTemp = (PSTREAMBUFFER)qhInProcess.Head(); // configure the wave device ((PWAVEAUDIO)pahw)->ConfigDev(this, &_configinfo); if(ulStreamType == STREAM_WAVE_PLAY) { fragsize = _configinfo.ulPCMConsumeRate/64; //start with 64 irqs/sec } else fragsize = _configinfo.ulPCMConsumeRate/32; //start with 32 irqs/sec (no need for more) //if the buffer is smaller than our predefined fragmentsize (*2), then correct it //I assume here that buffers sizes don't radically change (except the last one) //while playing a stream. If they do get a lot smaller, then we'll run into problems. //There's nothing we can do about it as the fragment size can't be changed //while the stream is playing. if(pTemp->ulBuffsz/2 < fragsize) { fragsize = pTemp->ulBuffsz/2; if(fragsize < _configinfo.ulPCMConsumeRate/256) {//lower limit; don't accept extremely small buffers fragsize = _configinfo.ulPCMConsumeRate/256; } } OSS16_StreamSetFragment(this, fragsize); dprintf(("WAVESTREAM::StartStream: Fragment size %d", (USHORT)fragsize)); _ulBytesProcessed = 0; fUnderrun = FALSE; ulStreamState = STREAM_STREAMING; //Adding the first buffer also starts playback if(ulStreamType == STREAM_WAVE_PLAY) { AddBuffers(TRUE); } else { if(!fRecSrcIOCTL90) OSS16_SetVolume(this, MIX_SETINPUTSRC, inputsrc); if(!fRecGainIOCTL90) OSS16_SetVolume(this, MIX_SETINPUTGAIN, inputgain); OSS16_StartStream(this); } //Must set volume after adding buffers (voices inside sblive driver might not //be allocated otherwise (first start) ) if(ulStreamType == STREAM_WAVE_PLAY) OSS16_SetWaveOutVol(this, volume); dprintf(("WAVESTREAM::StartStream %lx", ulStreamId)); return NO_ERROR; }
int main(void) { IPTR args[NOOFARGS] = { (IPTR)NULL, (IPTR)0 }; struct RDArgs *rda; int result; int error = RETURN_OK; ULONG buffers = 0; rda = ReadArgs(ARG_TEMPLATE, args, NULL); if (rda != NULL) { STRPTR drive = (STRPTR)args[ARG_DRIVE]; ULONG *bufsptr = (ULONG *)args[ARG_BUFFERS]; if (bufsptr != NULL) { buffers = *bufsptr; } result = AddBuffers(drive, buffers); if (result == -1) { Printf("%s has %ld buffers\n", drive, IoErr()); } else if (result > 0) { Printf("%s has %ld buffers\n", drive, (LONG)result); } else { PrintFault(IoErr(), "AddBuffers"); error = RETURN_FAIL; } FreeArgs(rda); } else { PrintFault(IoErr(), "AddBuffers"); error = RETURN_FAIL; } return error; }
ULONG WAVESTREAM::ResumeStream(void) { // configure the wave device ((PWAVEAUDIO)pahw)->ConfigDev(this, &_configinfo); if(ulStreamType == STREAM_WAVE_PLAY) OSS16_SetWaveOutVol(this, volume); dprintf(("WAVESTREAM::ResumeStream %lx", ulStreamId)); _ulBytesProcessed = 0; fUnderrun = FALSE; ulStreamState = STREAM_STREAMING; //Adding the first buffer also starts playback AddBuffers(TRUE); return NO_ERROR; }