📄 multivoc.c
字号:
Checks if the voice associated with the specified handle is playing.---------------------------------------------------------------------*/int32_t MV_VoicePlaying(int32_t handle){ VoiceNode *voice; if (!MV_Installed) { MV_SetErrorCode(MV_NotInstalled); return(FALSE); } voice = MV_GetVoice(handle); if (voice == NULL) { return(FALSE); } return(TRUE);}/*--------------------------------------------------------------------- Function: MV_KillAllVoices Stops output of all currently active voices.---------------------------------------------------------------------*/int32_t MV_KillAllVoices(void){ if (!MV_Installed) { MV_SetErrorCode(MV_NotInstalled); return(MV_Error); } // Remove all the voices from the list while (VoiceList.next != &VoiceList) { MV_Kill(VoiceList.next->handle); } return(MV_Ok);}/*--------------------------------------------------------------------- Function: MV_Kill Stops output of the voice associated with the specified handle.---------------------------------------------------------------------*/int32_t MV_Kill(int32_t handle){ VoiceNode *voice; unsigned flags; uint32_t callbackval; if (!MV_Installed) { MV_SetErrorCode(MV_NotInstalled); return(MV_Error); } flags = DisableInterrupts(); voice = MV_GetVoice(handle); if (voice == NULL) { RestoreInterrupts(flags); MV_SetErrorCode(MV_VoiceNotFound); return(MV_Error); } callbackval = voice->callbackval; MV_StopVoice(voice); RestoreInterrupts(flags); if (MV_CallBackFunc) { MV_CallBackFunc(callbackval); } return(MV_Ok);}/*--------------------------------------------------------------------- Function: MV_VoicesPlaying Determines the number of currently active voices.---------------------------------------------------------------------*/int32_t MV_VoicesPlaying(void){ VoiceNode *voice; int32_t NumVoices = 0; unsigned flags; if (!MV_Installed) { MV_SetErrorCode(MV_NotInstalled); return(0); } flags = DisableInterrupts(); for (voice = VoiceList.next; voice != &VoiceList; voice = voice->next) { NumVoices++; } RestoreInterrupts(flags); return(NumVoices);}/*--------------------------------------------------------------------- Function: MV_AllocVoice Retrieve an inactive or lower priority voice for output.---------------------------------------------------------------------*/VoiceNode *MV_AllocVoice(int32_t priority){ VoiceNode *voice; VoiceNode *node; unsigned flags;//return(NULL); if (MV_Recording) { return(NULL); } flags = DisableInterrupts(); // Check if we have any free voices if (LL_Empty(&VoicePool, next, prev)) { // check if we have a higher priority than a voice that is playing. voice = VoiceList.next; for (node = voice->next; node != &VoiceList; node = node->next) { if (node->priority < voice->priority) { voice = node; } } if (priority >= voice->priority) { MV_Kill(voice->handle); } } // Check if any voices are in the voice pool if (LL_Empty(&VoicePool, next, prev)) { // No free voices RestoreInterrupts(flags); return(NULL); } voice = VoicePool.next; LL_Remove(voice, next, prev); RestoreInterrupts(flags); // Find a free voice handle do { MV_VoiceHandle++; if (MV_VoiceHandle < MV_MinVoiceHandle) { MV_VoiceHandle = MV_MinVoiceHandle; } } while (MV_VoicePlaying(MV_VoiceHandle)); voice->handle = MV_VoiceHandle; return(voice);}/*--------------------------------------------------------------------- Function: MV_VoiceAvailable Checks if a voice can be play at the specified priority.---------------------------------------------------------------------*/int32_t MV_VoiceAvailable(int32_t priority){ VoiceNode *voice; VoiceNode *node; unsigned flags; // Check if we have any free voices if (!LL_Empty(&VoicePool, next, prev)) { return(TRUE); } flags = DisableInterrupts(); // check if we have a higher priority than a voice that is playing. voice = VoiceList.next; for (node = VoiceList.next; node != &VoiceList; node = node->next) { if (node->priority < voice->priority) { voice = node; } } RestoreInterrupts(flags); if ((voice != &VoiceList) && (priority >= voice->priority)) { return(TRUE); } return(FALSE);}/*--------------------------------------------------------------------- Function: MV_SetVoicePitch Sets the pitch for the specified voice.---------------------------------------------------------------------*/void MV_SetVoicePitch(VoiceNode *voice, uint32_t rate, int32_t pitchoffset){ voice->SamplingRate = rate; voice->PitchScale = PITCH_GetScale(pitchoffset); voice->RateScale = (rate * voice->PitchScale) / MV_MixRate; // Multiply by MixBufferSize - 1 voice->FixedPointBufferSize = (voice->RateScale * MixBufferSize) - voice->RateScale;}/*--------------------------------------------------------------------- Function: MV_SetPitch Sets the pitch for the voice associated with the specified handle.---------------------------------------------------------------------*/int32_t MV_SetPitch(int32_t handle, int32_t pitchoffset){ VoiceNode *voice; if (!MV_Installed) { MV_SetErrorCode(MV_NotInstalled); return(MV_Error); } voice = MV_GetVoice(handle); if (voice == NULL) { MV_SetErrorCode(MV_VoiceNotFound); return(MV_Error); } MV_SetVoicePitch(voice, voice->SamplingRate, pitchoffset); return(MV_Ok);}/*--------------------------------------------------------------------- Function: MV_SetFrequency Sets the frequency for the voice associated with the specified handle.---------------------------------------------------------------------*/int32_t MV_SetFrequency(int32_t handle, int32_t frequency){ VoiceNode *voice; if (!MV_Installed) { MV_SetErrorCode(MV_NotInstalled); return(MV_Error); } voice = MV_GetVoice(handle); if (voice == NULL) { MV_SetErrorCode(MV_VoiceNotFound); return(MV_Error); } MV_SetVoicePitch(voice, frequency, 0); return(MV_Ok);}/*--------------------------------------------------------------------- Function: MV_GetVolumeTable Returns a pointer to the volume table associated with the specified volume.---------------------------------------------------------------------*/static int16_t *MV_GetVolumeTable(int32_t vol){ int32_t volume; int16_t *table; volume = MIX_VOLUME(vol); table = (int16_t*)&MV_VolumeTable[ volume ]; return(table);}/*--------------------------------------------------------------------- Function: MV_SetVoiceMixMode Selects which method should be used to mix the voice.---------------------------------------------------------------------*/static void MV_SetVoiceMixMode(VoiceNode *voice){ unsigned flags; int32_t test; flags = DisableInterrupts(); test = T_DEFAULT; if (MV_Bits == 8) { test |= T_8BITS; } if (voice->bits == 16) { test |= T_16BITSOURCE; } if (MV_Channels == 1) { test |= T_MONO; } else { if (IS_QUIET(voice->RightVolume)) { test |= T_RIGHTQUIET; } else if (IS_QUIET(voice->LeftVolume)) { test |= T_LEFTQUIET; } } // Default case voice->mix = MV_Mix8BitMono; switch (test) { case T_8BITS | T_MONO | T_16BITSOURCE : voice->mix = MV_Mix8BitMono16; break; case T_8BITS | T_MONO : voice->mix = MV_Mix8BitMono; break; case T_8BITS | T_16BITSOURCE | T_LEFTQUIET : MV_LeftVolume = MV_RightVolume; voice->mix = MV_Mix8BitMono16; break; case T_8BITS | T_LEFTQUIET : MV_LeftVolume = MV_RightVolume; voice->mix = MV_Mix8BitMono; break; case T_8BITS | T_16BITSOURCE | T_RIGHTQUIET : voice->mix = MV_Mix8BitMono16; break; case T_8BITS | T_RIGHTQUIET : voice->mix = MV_Mix8BitMono; break; case T_8BITS | T_16BITSOURCE : voice->mix = MV_Mix8BitStereo16; break; case T_8BITS : voice->mix = MV_Mix8BitStereo; break; case T_MONO | T_16BITSOURCE : voice->mix = MV_Mix16BitMono16; break; case T_MONO : voice->mix = MV_Mix16BitMono; break; case T_16BITSOURCE | T_LEFTQUIET : MV_LeftVolume = MV_RightVolume; voice->mix = MV_Mix16BitMono16; break; case T_LEFTQUIET : MV_LeftVolume = MV_RightVolume; voice->mix = MV_Mix16BitMono; break; case T_16BITSOURCE | T_RIGHTQUIET : voice->mix = MV_Mix16BitMono16; break; case T_RIGHTQUIET : voice->mix = MV_Mix16BitMono; break; case T_16BITSOURCE : voice->mix = MV_Mix16BitStereo16; break; case T_SIXTEENBIT_STEREO : voice->mix = MV_Mix16BitStereo; break; default : voice->mix = MV_Mix8BitMono; } RestoreInterrupts(flags);}/*--------------------------------------------------------------------- Function: MV_SetVoiceVolume Sets the stereo and mono volume level of the voice associated with the specified handle.---------------------------------------------------------------------*/void MV_SetVoiceVolume(VoiceNode *voice, int32_t vol, int32_t left, int32_t right){ if (MV_Channels == 1) { left = vol; right = vol; } if (MV_SwapLeftRight) { // SBPro uses reversed panning voice->LeftVolume = MV_GetVolumeTable(right); voice->RightVolume = MV_GetVolumeTable(left); } else { voice->LeftVolume = MV_GetVolumeTable(left); voice->RightVolume = MV_GetVolumeTable(right); } MV_SetVoiceMixMode(voice);}/*--------------------------------------------------------------------- Function: MV_EndLooping Stops the voice associated with the specified handle from looping without stoping the sound.---------------------------------------------------------------------*/int32_t MV_EndLooping(int32_t handle){ VoiceNode *voice; unsigned flags; if (!MV_Installed) { MV_SetErrorCode(MV_NotInstalled); return(MV_Error); } flags = DisableInterrupts(); voice = MV_GetVoice(handle); if (voice == NULL) { RestoreInterrupts(flags); MV_SetErrorCode(MV_VoiceNotFound); return(MV_Warning); } voice->LoopCount = 0; voice->LoopStart = NULL; voice->LoopEnd = NULL; RestoreInterrupts(flags); return(MV_Ok);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -