📄 multivoc.c
字号:
{ MV_CallBackFunc(voice->callbackval); } } } return MV_MixPage;}/*--------------------------------------------------------------------- Function: MV_GetNextVOCBlock Interperate the information of a VOC format sound file.---------------------------------------------------------------------*/static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice){ char *ptr; int32_t blocktype; int32_t lastblocktype; uint32_t blocklength = 0; uint32_t samplespeed = 0; uint32_t tc = 0; int32_t packtype; int32_t voicemode; int32_t done; unsigned BitsPerSample; unsigned Channels; unsigned Format; if (voice->BlockLength > 0) { voice->position -= voice->length; voice->sound += voice->length >> 16; if (voice->bits == 16) { voice->sound += voice->length >> 16; } voice->length = min(voice->BlockLength, 0x8000); voice->BlockLength -= voice->length; voice->length <<= 16; return(KeepPlaying); } if ((voice->length > 0) && (voice->LoopEnd != NULL) && (voice->LoopStart != NULL)) { voice->BlockLength = voice->LoopSize; voice->sound = voice->LoopStart; voice->position = 0; voice->length = min(voice->BlockLength, 0x8000); voice->BlockLength -= voice->length; voice->length <<= 16; return(KeepPlaying); } ptr = (char *)voice->NextBlock; voice->Playing = TRUE; voicemode = 0; lastblocktype = 0; packtype = 0; done = FALSE; while (!done) { // Stop playing if we get a NULL pointer if (ptr == NULL) { voice->Playing = FALSE; done = TRUE; break; } blocktype = (int32_t)*ptr; blocklength = (*(uint32_t *)(ptr + 1)) & 0x00ffffff; ptr += 4; switch (blocktype) { case 0 : // End of data if ((voice->LoopStart == NULL) || ((uint32_t *)voice->LoopStart >= (uint32_t *)(ptr - 4))) { voice->Playing = FALSE; done = TRUE; } else { voice->BlockLength = (char*)(ptr - 4) - voice->LoopStart; voice->sound = voice->LoopStart; voice->position = 0; voice->length = min(voice->BlockLength, 0x8000); voice->BlockLength -= voice->length; voice->length <<= 16; return(KeepPlaying); } break; case 1 : // Sound data block voice->bits = 8; if (lastblocktype != 8) { tc = (uint32_t)*ptr << 8; packtype = *(ptr + 1); } ptr += 2; blocklength -= 2; samplespeed = 256000000L / (65536 - tc); // Skip packed or stereo data if ((packtype != 0) || (voicemode != 0)) { ptr += blocklength; } else { done = TRUE; } voicemode = 0; break; case 2 : // Sound continuation block samplespeed = voice->SamplingRate; done = TRUE; break; case 3 : // Silence // Not implimented. ptr += blocklength; break; case 4 : // Marker // Not implimented. ptr += blocklength; break; case 5 : // ASCII string // Not implimented. ptr += blocklength; break; case 6 : // Repeat begin if (voice->LoopEnd == NULL) { voice->LoopCount = *(uint16_t *)ptr; voice->LoopStart = (char *)(ptr + blocklength); } ptr += blocklength; break; case 7 : // Repeat end ptr += blocklength; if (lastblocktype == 6) { voice->LoopCount = 0; } else { if ((voice->LoopCount > 0) && (voice->LoopStart != NULL)) { ptr = (char *)voice->LoopStart; if (voice->LoopCount < 0xffff) { voice->LoopCount--; if (voice->LoopCount == 0) { voice->LoopStart = NULL; } } } } break; case 8 : // Extended block voice->bits = 8; tc = *(uint16_t *)ptr; packtype = *(ptr + 2); voicemode = *(ptr + 3); ptr += blocklength; break; case 9 : // New sound data block samplespeed = *(uint32_t *)ptr; BitsPerSample = (unsigned)*(ptr + 4); Channels = (unsigned)*(ptr + 5); Format = (unsigned)*(uint16_t *)(ptr + 6); if ((BitsPerSample == 8) && (Channels == 1) && (Format == VOC_8BIT)) { ptr += 12; blocklength -= 12; voice->bits = 8; done = TRUE; } else if ((BitsPerSample == 16) && (Channels == 1) && (Format == VOC_16BIT)) { ptr += 12; blocklength -= 12; voice->bits = 16; done = TRUE; } else { ptr += blocklength; } break; default : // Unknown data. Probably not a VOC file. voice->Playing = FALSE; done = TRUE; break; } lastblocktype = blocktype; } if (voice->Playing) { voice->NextBlock = (char *)(ptr + blocklength); voice->sound = (char *)ptr; voice->SamplingRate = samplespeed; voice->RateScale = (voice->SamplingRate * voice->PitchScale) / MV_MixRate; // Multiply by MixBufferSize - 1 voice->FixedPointBufferSize = (voice->RateScale * MixBufferSize) - voice->RateScale; if (voice->LoopEnd != NULL) { if (blocklength > (uintptr_t)voice->LoopEnd) { blocklength = (uintptr_t)voice->LoopEnd; } else { voice->LoopEnd = (char *)blocklength; } voice->LoopStart = voice->sound + (uintptr_t)voice->LoopStart; voice->LoopEnd = voice->sound + (uintptr_t)voice->LoopEnd; voice->LoopSize = voice->LoopEnd - voice->LoopStart; } if (voice->bits == 16) { blocklength /= 2; } voice->position = 0; voice->length = min(blocklength, 0x8000); voice->BlockLength = blocklength - voice->length; voice->length <<= 16; MV_SetVoiceMixMode(voice); return(KeepPlaying); } return(NoMoreData);}/*--------------------------------------------------------------------- Function: MV_GetNextDemandFeedBlock Controls playback of demand fed data.---------------------------------------------------------------------*/playbackstatus MV_GetNextDemandFeedBlock(VoiceNode *voice){ if (voice->BlockLength > 0) { voice->position -= voice->length; voice->sound += voice->length >> 16; voice->length = min(voice->BlockLength, 0x8000); voice->BlockLength -= voice->length; voice->length <<= 16; return(KeepPlaying); } if (voice->DemandFeed == NULL) { return(NoMoreData); } voice->position = 0; (voice->DemandFeed)(&voice->sound, &voice->BlockLength); voice->length = min(voice->BlockLength, 0x8000); voice->BlockLength -= voice->length; voice->length <<= 16; if ((voice->length > 0) && (voice->sound != NULL)) { return(KeepPlaying); } return(NoMoreData);}/*--------------------------------------------------------------------- Function: MV_GetNextRawBlock Controls playback of demand fed data.---------------------------------------------------------------------*/playbackstatus MV_GetNextRawBlock(VoiceNode *voice){ if (voice->BlockLength <= 0) { if (voice->LoopStart == NULL) { voice->Playing = FALSE; return(NoMoreData); } voice->BlockLength = voice->LoopSize; voice->NextBlock = voice->LoopStart; voice->length = 0; voice->position = 0; } voice->sound = voice->NextBlock; voice->position -= voice->length; voice->length = min(voice->BlockLength, 0x8000); voice->NextBlock += voice->length; if (voice->bits == 16) { voice->NextBlock += voice->length; } voice->BlockLength -= voice->length; voice->length <<= 16; return(KeepPlaying);}/*--------------------------------------------------------------------- Function: MV_GetNextWAVBlock Controls playback of demand fed data.---------------------------------------------------------------------*/playbackstatus MV_GetNextWAVBlock(VoiceNode *voice){ if (voice->BlockLength <= 0) { if (voice->LoopStart == NULL) { voice->Playing = FALSE; return(NoMoreData); } voice->BlockLength = voice->LoopSize; voice->NextBlock = voice->LoopStart; voice->length = 0; voice->position = 0; } voice->sound = voice->NextBlock; voice->position -= voice->length; voice->length = min(voice->BlockLength, 0x8000); voice->NextBlock += voice->length; if (voice->bits == 16) { voice->NextBlock += voice->length; } voice->BlockLength -= voice->length; voice->length <<= 16; return(KeepPlaying);}/*--------------------------------------------------------------------- Function: MV_GetNextOGGBlock Controls playback of demand fed data.---------------------------------------------------------------------*/void downsample(char *ptr,int32_t size,int32_t factor){ int16_t *pti=(int16_t *)ptr;int32_t i,j,sum; for (i=0;i<size>>factor;i++) { sum=0; for (j=0;j<1<<factor;j++)sum+=pti[(i<<factor)+j]; pti[i]=sum>>factor; }}playbackstatus MV_GetNextOGGBlock(VoiceNode *voice){ int32_t sz; int32_t size=0; int32_t section,result;// initprintf("_%d %d, %d\n",voice->callbackval,voice->position,voice->BlockLength); if (voice->BlockLength <= 0) { if (voice->LoopStart == NULL) {// initprintf("END %d\n",voice->callbackval); voice->Playing = FALSE; return(NoMoreData); }// initprintf("repeat 2\n"); voice->BlockLength = voice->LoopSize; voice->length = 0; voice->position = 0; ov_pcm_seek(&voice->OGGstream.oggStream,0); } voice->position -= voice->length; sz=voice->length = min(voice->BlockLength, 0x8000); voice->BlockLength -= voice->length; voice->length <<= 16; sz<<=voice->downsample+1; while (size<sz) { result=ov_read(&voice->OGGstream.oggStream,voice->bufsnd+(size>>voice->downsample),sz-size,0,2,1,§ion); if (result> 0) { downsample(voice->bufsnd+(size>>voice->downsample),result,voice->downsample); size+=result; } else if (result==0) {// initprintf("!repeat %d\n",voice->callbackval); voice->BlockLength=0; voice->length=size<<16;break; } else { initprintf("#%d\n",result); break; } } voice->sound=voice->bufsnd; return(KeepPlaying);}/*--------------------------------------------------------------------- Function: MV_ServiceRecord Starts recording of the waiting buffer.---------------------------------------------------------------------*/#if 0static void MV_ServiceRecord(void){ if (MV_RecordFunc) { MV_RecordFunc(MV_MixBuffer[ 0 ] + MV_MixPage * MixBufferSize, MixBufferSize); } // Toggle which buffer we'll mix next MV_MixPage++; if (MV_MixPage >= NumberOfBuffers) { MV_MixPage = 0; }}#endif/*--------------------------------------------------------------------- Function: MV_GetVoice Locates the voice with the specified handle.---------------------------------------------------------------------*/VoiceNode *MV_GetVoice(int32_t handle){ VoiceNode *voice; unsigned flags; flags = DisableInterrupts(); for (voice = VoiceList.next; voice != &VoiceList; voice = voice->next) { if (handle == voice->handle) { break; } } RestoreInterrupts(flags); if (voice == &VoiceList) { MV_SetErrorCode(MV_VoiceNotFound); voice = NULL; } return(voice);}/*--------------------------------------------------------------------- Function: MV_VoicePlaying
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -