⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multivoc.c

📁 An interactive water fountain. A realistic water source in your pocket with full control. Contro
💻 C
📖 第 1 页 / 共 5 页
字号:
/*Copyright (C) 1994-1995 Apogee Software, Ltd.This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.Modifications for JonoF's port by Jonathon Fowler (jonof@edgenetwk.com)*//**********************************************************************   module: MULTIVOC.C   author: James R. Dose   date:   December 20, 1993   Routines to provide multichannel digitized sound playback for   Sound Blaster compatible sound cards.   (c) Copyright 1993 James R. Dose.  All Rights Reserved.**********************************************************************/#include <stdlib.h>#include <string.h>#ifndef _MSC_VER#include <unistd.h>#endif#include <duke3d.h>#ifdef _WIN32#include "dsoundout.h"#ifdef USE_OPENAL#include "openal.h"#endif#else#include "dsl.h"#endif#include "compat.h"#include "baselayer.h"#include "linklist.h"#include "pitch.h"#include "multivoc.h"#include "_multivc.h"#define STEREO      1#define SIXTEEN_BIT 2#define MONO_8BIT    0#define STEREO_8BIT  (STEREO)#define MONO_16BIT   (SIXTEEN_BIT)#define STEREO_16BIT (STEREO | SIXTEEN_BIT)#define IS_QUIET(ptr)  ((void *)(ptr) == (void *)&MV_VolumeTable[ 0 ])static int32_t MV_ReverbLevel;static int32_t MV_ReverbDelay;static VOLUME16 *MV_ReverbTable = NULL;//static signed short MV_VolumeTable[ MV_MaxVolume + 1 ][ 256 ];static int16_t MV_VolumeTable[ 63 + 1 ][ 256 ];//static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ];static Pan MV_PanTable[ MV_NumPanPositions ][ 63 + 1 ];static int32_t MV_Installed   = FALSE;static int32_t MV_SoundCard   = -1;static int32_t MV_TotalVolume = MV_MaxTotalVolume;static int32_t MV_MaxVoices   = 1;static int32_t MV_Recording;static int32_t MV_BufferSize = 0;static int32_t MV_BufferLength;static int32_t MV_NumberOfBuffers = NumberOfBuffers;static int32_t MV_MixMode    = MONO_8BIT;static int32_t MV_Channels   = 1;static int32_t MV_Bits       = 8;static int32_t MV_Silence    = SILENCE_8BIT;static int32_t MV_SwapLeftRight = FALSE;static int32_t MV_RequestedMixRate;static int32_t MV_MixRate;static int32_t MV_BuffShift;static int32_t MV_TotalMemory;static int32_t MV_BufferEmpty[ NumberOfBuffers ];char *MV_MixBuffer[ NumberOfBuffers + 1 ];static char *MV_MixBufferPtr = NULL;static VoiceNode *MV_Voices = NULL;static VoiceNode VoiceList;static VoiceNode VoicePool;int32_t MV_MixPage      = 0;static int32_t MV_VoiceHandle  = MV_MinVoiceHandle;static void(*MV_CallBackFunc)(uint32_t) = NULL;static void(*MV_RecordFunc)(char *ptr, int32_t length) = NULL;static void(*MV_MixFunction)(VoiceNode *voice, int32_t buffer);static int32_t MV_MaxVolume = 63;char  *MV_HarshClipTable;char  *MV_MixDestination;int16_t *MV_LeftVolume;int16_t *MV_RightVolume;int32_t MV_SampleSize = 1;int32_t MV_RightChannelOffset;uint32_t MV_MixPosition;int32_t MV_ErrorCode = MV_Ok;#define MV_SetErrorCode(status) \   MV_ErrorCode   = (status);/*---------------------------------------------------------------------   Function: ClearBuffer_DW   Function code relocated from _multivc.h due to linking issues.---------------------------------------------------------------------*/void ClearBuffer_DW(void *ptr, int32_t data, int32_t length){    int32_t *pptr = ptr;    for (; length>0; length--) *(pptr++) = data;}/*---------------------------------------------------------------------   Function: MV_ErrorString   Returns a pointer to the error message associated with an error   number.  A -1 returns a pointer the current error.---------------------------------------------------------------------*/char *MV_ErrorString(int32_t ErrorNumber){    char *ErrorString;    switch (ErrorNumber)    {    case MV_Warning :    case MV_Error :        ErrorString = MV_ErrorString(MV_ErrorCode);        break;    case MV_Ok :        ErrorString = "Multivoc ok.";        break;    case MV_UnsupportedCard :        ErrorString = "Selected sound card is not supported by Multivoc.";        break;    case MV_NotInstalled :        ErrorString = "Multivoc not installed.";        break;    case MV_NoVoices :        ErrorString = "No free voices available to Multivoc.";        break;    case MV_NoMem :        ErrorString = "Out of memory in Multivoc.";        break;    case MV_VoiceNotFound :        ErrorString = "No voice with matching handle found.";        break;    case MV_BlasterError :#if defined(_WIN32)        ErrorString = DSOUND_ErrorString(DSOUND_ErrorCode);#else        ErrorString = DSL_ErrorString(DSL_ErrorCode);#endif        break;    case MV_DPMI_Error :        ErrorString = "DPMI Error in Multivoc.";        break;    case MV_InvalidVOCFile :        ErrorString = "Invalid VOC file passed in to Multivoc.";        break;    case MV_InvalidWAVFile :        ErrorString = "Invalid WAV file passed in to Multivoc.";        break;    case MV_InvalidOGGFile :        ErrorString = "Invalid OGG file passed in to Multivoc.";        break;    case MV_InvalidMixMode :        ErrorString = "Invalid mix mode request in Multivoc.";        break;    case MV_IrqFailure :        ErrorString = "Playback failed, possibly due to an invalid or conflicting IRQ.";        break;    case MV_DMAFailure :        ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel.";        break;    case MV_DMA16Failure :        ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel.  \n"                      "Make sure the 16-bit DMA channel is correct.";        break;    case MV_NullRecordFunction :        ErrorString = "Null record function passed to MV_StartRecording.";        break;    default :        ErrorString = "Unknown Multivoc error code.";        break;    }    return(ErrorString);}/**********************************************************************   Memory locked functions:**********************************************************************//*---------------------------------------------------------------------   Function: MV_GetBufferSize   Returns the buffer size for the given samplerate.---------------------------------------------------------------------*/#if defined(_WIN32)#define BASEBUFSZ (512+128)static uint32_t MV_GetBufferSize(unsigned samplerate){    static unsigned lastsr = 0, lastbufsz = 0;    if (samplerate == lastsr) return lastbufsz;    lastsr = samplerate;    lastbufsz = (samplerate*BASEBUFSZ/22050)&(~15);#ifdef RENDERTYPEWIN    {        extern int32_t is_vista;        if (is_vista)            lastbufsz = (samplerate*BASEBUFSZ/22050*2)&(~15);    }#endif    return lastbufsz;}#endif/*---------------------------------------------------------------------   Function: MV_Mix   Mixes the sound into the buffer.---------------------------------------------------------------------*/static void MV_Mix(VoiceNode *voice, int32_t buffer){    char          *start;    int32_t length;    int32_t voclength;    uint32_t position;    uint32_t rate;    uint32_t FixedPointBufferSize;    if ((voice->length == 0) && (voice->GetSound(voice) != KeepPlaying))    {        return;    }    length               = MixBufferSize;    FixedPointBufferSize = voice->FixedPointBufferSize;    MV_MixDestination    = MV_MixBuffer[ buffer ];    MV_LeftVolume        = voice->LeftVolume;    MV_RightVolume       = voice->RightVolume;    if ((MV_Channels == 2) && (IS_QUIET(MV_LeftVolume)))    {        MV_LeftVolume      = MV_RightVolume;        MV_MixDestination += MV_RightChannelOffset;    }    // Add this voice to the mix    while (length > 0)    {        start    = voice->sound;        rate     = voice->RateScale;        position = voice->position;        // Check if the last sample in this buffer would be        // beyond the length of the sample block        if ((position + FixedPointBufferSize) >= voice->length)        {            if (position < voice->length)            {                voclength = (voice->length - position + rate - 1) / rate;            }            else            {                voice->GetSound(voice);                return;            }        }        else        {            voclength = length;        }        voice->mix(position, rate, start, voclength);        if (voclength & 1)        {            MV_MixPosition += rate;            voclength -= 1;        }        voice->position = MV_MixPosition;        length -= voclength;        if (voice->position >= voice->length)        {            // Get the next block of sound            if (voice->GetSound(voice) != KeepPlaying)            {                return;            }            if (length > 0)            {                // Get the position of the last sample in the buffer                FixedPointBufferSize = voice->RateScale * (length - 1);            }        }    }}/*---------------------------------------------------------------------   Function: MV_PlayVoice   Adds a voice to the play list.---------------------------------------------------------------------*/void MV_PlayVoice(VoiceNode *voice){    unsigned flags;    flags = DisableInterrupts();    LL_SortedInsertion(&VoiceList, voice, prev, next, VoiceNode, priority);//    if(!voice->bufsnd)voice->bufsnd=(char *)Bcalloc(0x8000*4,sizeof(uint8_t));//    if(!voice->bufsnd)initprintf("Attention. It gonna crash! Thank you."); // FIXME: change the msg    RestoreInterrupts(flags);}/*---------------------------------------------------------------------   Function: MV_StopVoice   Removes the voice from the play list and adds it to the free list.---------------------------------------------------------------------*/void MV_StopVoice(VoiceNode *voice){    uint32_t flags;    flags = DisableInterrupts();//    if(!voice->bufsnd)Bfree(voice->bufsnd);    // move the voice from the play list to the free list    LL_Remove(voice, next, prev);    LL_Add(&VoicePool, voice, next, prev);    RestoreInterrupts(flags);}/*---------------------------------------------------------------------   Function: MV_ServiceVoc   Starts playback of the waiting buffer and mixes the next one.---------------------------------------------------------------------*/// static int32_t backcolor = 1;int32_t MV_ServiceVoc(int32_t buffer){    VoiceNode *voice;    VoiceNode *next;    // Get the currently playing buffer#if defined(_WIN32)    MV_MixPage   = buffer;#else    UNREFERENCED_PARAMETER(buffer);#endif    // Toggle which buffer we'll mix next    MV_MixPage++;    if (MV_MixPage >= MV_NumberOfBuffers)    {        MV_MixPage -= MV_NumberOfBuffers;    }    if (MV_ReverbLevel == 0)    {        // Initialize buffer        //Commented out so that the buffer is always cleared.        //This is so the guys at Echo Speech can mix into the        //buffer even when no sounds are playing.        //if (!MV_BufferEmpty[ MV_MixPage ])        {            ClearBuffer_DW(MV_MixBuffer[ MV_MixPage ], MV_Silence, MV_BufferSize >> 2);            MV_BufferEmpty[ MV_MixPage ] = TRUE;        }    }    else    {        char *end;        char *source;        char *dest;        int32_t count;        int32_t length;        end = MV_MixBuffer[ 0 ] + MV_BufferLength;        dest = MV_MixBuffer[ MV_MixPage ];        source = MV_MixBuffer[ MV_MixPage ] - MV_ReverbDelay;        if (source < MV_MixBuffer[ 0 ])        {            source += MV_BufferLength;        }        length = MV_BufferSize;        while (length > 0)        {            count = length;            if (source + count > end)            {                count = end - source;            }            if (MV_Bits == 16)            {                if (MV_ReverbTable != NULL)                {                    MV_16BitReverb(source, dest, MV_ReverbTable, count / 2);                }                else                {                    MV_16BitReverbFast(source, dest, count / 2, MV_ReverbLevel);                }            }            else            {                if (MV_ReverbTable != NULL)                {                    MV_8BitReverb((char *)source, (char *)dest, MV_ReverbTable, count);                }                else                {                    MV_8BitReverbFast((char *)source, (char *)dest, count, MV_ReverbLevel);                }            }            // if we go through the loop again, it means that we've wrapped around the buffer            source  = MV_MixBuffer[ 0 ];            dest   += count;            length -= count;        }    }    // Play any waiting voices    for (voice = VoiceList.next; voice != &VoiceList; voice = next)    {//      if ((voice < &MV_Voices[ 0 ]) || (voice > &MV_Voices[ 8 ]))//         {//         SetBorderColor(backcolor++);//         break;//         }        MV_BufferEmpty[ MV_MixPage ] = FALSE;        MV_MixFunction(voice, MV_MixPage);        next = voice->next;        // Is this voice done?        if (!voice->Playing)        {            MV_StopVoice(voice);            if (MV_CallBackFunc)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -