123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653 |
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 RWS Inc, All Rights Reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of version 2 of the GNU General Public License as published by
- // the Free Software Foundation
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY 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 License along
- // with this program; if not, write to the Free Software Foundation, Inc.,
- // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- //
- ///////////////////////////////////////////////////////////////////////////////
- //
- // SndFx.cpp
- //
- // History:
- // 09/06/96 JMI Started.
- //
- // 09/10/96 JMI Now uses a precalculated table (generated by a call to
- // SetFadeAccuracy()) to do fades.
- //
- // 09/10/96 JMI Now effects can optionally have a destination other than
- // the source.
- //
- // 09/11/96 JMI Fade outs for 8 bit were sending the fade in variables
- // to the decimate unsigned template.
- //
- // 09/24/96 MJR Added <stdlib.h> so it would compile on Mac.
- //
- // 10/30/96 JMI Changed:
- // Old label: New label:
- // ========= =========
- // CSndFx RSndFx
- // MAX_BITSPERSAMPLE RSP_SNDFX_MAX_BITSPERSAMPLE
- // NUM_FADE_INTERVALS RSP_SNDFX_NUM_FADE_INTERVALS
- // SNDFX_* * Macros changed to enum/typedef.
- // m_fx m_fx
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // Implements sound effects on PCM data.
- //
- //////////////////////////////////////////////////////////////////////////////
- #include <stdlib.h>
- #include "Blue.h"
- #ifdef PATHS_IN_INCLUDES
- #include "GREEN/SndFx/SndFx.h"
- #else
- #include "SndFx.h"
- #endif // PATHS_IN_INCLUDES
- //////////////////////////////////////////////////////////////////////////////
- // Initialize static member variables.
- //////////////////////////////////////////////////////////////////////////////
- RSndFx::PCMINFO RSndFx::ms_apcminfo[RSP_SNDFX_MAX_BITSPERSAMPLE + 1] = // Stores info
- // particular to each
- // PCM type.
- {
- { 0x00000000, 0x00000000 }, // 0 Bit.
- { 0x00000000, 0x00000001 }, // 1 Bit.
- { 0x00000000, 0x00000003 }, // 2 Bit.
- { 0x00000000, 0x00000007 }, // 3 Bit.
- { 0x00000000, 0x0000000F }, // 4 Bit.
- { 0x00000000, 0x0000001F }, // 5 Bit.
- { 0x00000000, 0x0000003F }, // 6 Bit.
- { 0x00000000, 0x0000007F }, // 7 Bit.
- { 0x00000000, 0x000000FF }, // 8 Bit.
- { 0x00000080, 0x000000FF }, // 9 Bit.
- { 0x00000100, 0x000001FF }, // 10 Bit.
- { 0x00000200, 0x000003FF }, // 11 Bit.
- { 0x00000400, 0x000007FF }, // 12 Bit.
- { 0x00000800, 0x00000FFF }, // 13 Bit.
- { 0x00001000, 0x00001FFF }, // 14 Bit.
- { 0x00002000, 0x00003FFF }, // 15 Bit.
- { -32768, 32767 }, // 16 Bit.
- { 0x00008000, 0x0000FFFF }, // 17 Bit.
- { 0x00010000, 0x0001FFFF }, // 18 Bit.
- { 0x00020000, 0x0003FFFF }, // 19 Bit.
- { 0x00040000, 0x0007FFFF }, // 20 Bit.
- { 0x00080000, 0x000FFFFF }, // 21 Bit.
- { 0x00100000, 0x001FFFFF }, // 22 Bit.
- { 0x00200000, 0x003FFFFF }, // 23 Bit.
- { 0x00400000, 0x007FFFFF }, // 24 Bit.
- { 0x00800000, 0x00FFFFFF }, // 25 Bit.
- { 0x01000000, 0x01FFFFFF }, // 26 Bit.
- { 0x02000000, 0x03FFFFFF }, // 27 Bit.
- { 0x04000000, 0x07FFFFFF }, // 28 Bit.
- { 0x08000000, 0x0FFFFFFF }, // 29 Bit.
- { 0x10000000, 0x1FFFFFFF }, // 30 Bit.
- { 0x20000000, 0x3FFFFFFF }, // 31 Bit.
- { 0x40000000, 0x7FFFFFFF }, // 32 Bit.
- };
- U8* RSndFx::ms_pu8Fade = NULL; // Unsigned 8 bit output
- // fade table.
- S16* RSndFx::ms_ps16Fade = NULL; // Signed 16 bit output
- // fade table.
- short RSndFx::ms_sNumFadeSteps = 0; // Number of fade steps.
- long RSndFx::ms_lSamplesPerSec = 0; // Samples per second.
- long RSndFx::ms_lBitsPerSample = 0; // Bits per sample.
- long RSndFx::ms_lNumChannels = 0; // Number of channels.
- long RSndFx::ms_lBitsPerSec = 0; // Number of bits per second.
- // Can be used to convert bytes to milliseconds
- // and convert milliseconds into bytes. See
- // macros BYTES2MS and MS2BYTES in SndFx.CPP.
- //////////////////////////////////////////////////////////////////////////////
- // Macros.
- //////////////////////////////////////////////////////////////////////////////
- // Converts bytes into milliseconds using a pre calculated variable.
- // 8000L consists of 8 (for bytes to bits) and 1000 (for seconds
- // to milliseconds).
- #define BYTES2MS(bytes) (((bytes) * 8000L) / ms_lBitsPerSec)
- // Converts milliseconds into bytes using a pre calculated variable.
- // 8000L consists of 8 (for bits to bytes) and 1000 (for milliseconds
- // to seconds).
- #define MS2BYTES(ms) (((ms) * ms_lBitsPerSec) / 8000L)
- #define PCM8_SILENCE 0x7F // 0x80 will not work for unsigned algorithm.
- #define PCM16_SILENCE 0x0000
- #define FIXED_POINT_DEPTH 1000 // Depth of fixed point notation (e.g.,
- // 1000 == depth of 1/1000).
- //////////////////////////////////////////////////////////////////////////////
- // Functions.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- //
- // Default Constructor.
- // Returns nothing.
- // (public)
- //
- //////////////////////////////////////////////////////////////////////////////
- RSndFx::RSndFx()
- {
- // Initializes members.
- Init();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Destructor.
- // Returns nothing.
- // (public)
- //
- //////////////////////////////////////////////////////////////////////////////
- RSndFx::~RSndFx()
- {
- // Clear and free.
- Clear();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Initialize instantiable members.
- // Returns nothing.
- // (public)
- //
- //////////////////////////////////////////////////////////////////////////////
- void RSndFx::Init(void)
- {
- // Initialize members.
- m_fx = NoFX; // Currently active effects.
-
- ///////////////// Fade In /////////////////////////////////////////
- m_lFadeInMillisecondsDuration = 0; // Original duration.
- m_lFadeInBytesDurationAffected = 0; // Amount left to fade.
- ///////////////// Fade Out ////////////////////////////////////////
- m_lFadeOutMillisecondsDuration = 0; // Original duration.
- m_lFadeOutBytesDurationRemaining = 0; // Amount left to fade.
- }
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Release any dynamic memory and reset variables.
- // Clears all effects.
- // (public)
- //
- ///////////////////////////////////////////////////////////////////////////////
- void RSndFx::Clear(void)
- {
- Init();
- }
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Release any dynamic memory referenced by static members.
- // (static/public)
- //
- ///////////////////////////////////////////////////////////////////////////////
- void RSndFx::CleanUp(void)
- {
- if (ms_pu8Fade != NULL)
- {
- free(ms_pu8Fade);
- ms_pu8Fade = NULL;
- }
- if (ms_ps16Fade != NULL)
- {
- free(ms_ps16Fade);
- ms_ps16Fade = NULL;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Reset effects to start over.
- //
- ///////////////////////////////////////////////////////////////////////////////
- void RSndFx::Reset(void)
- {
- ///////////////// Fade In /////////////////////////////////////////////////
- SetUpFadeIn(m_lFadeInMillisecondsDuration);
-
- ///////////////// Fade Out ////////////////////////////////////////////////
- SetUpFadeOut(m_lFadeOutMillisecondsDuration);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Sets the fade accuracy (i.e., the number of steps to perform a fade).
- // This costs sNumStemps * 256 * bits per sample / 8 bytes of memory.
- // This function should only be called after the bits per sample have
- // been set via a call to SetDataType().
- //
- //
- //
- // Power A
- // Power difference in dB = 10 log -------
- // Power B
- //
- // Every 3dB, the audible loudness doubles.
- // For acoustics, 0dB often means the threshold of hearing, 0.0002ubar
- // (Microbars: a bar is the "normal" pressure of air).
- // (static).
- //
- //////////////////////////////////////////////////////////////////////////////
- short RSndFx::SetFadeAccuracy( // Returns 0 on success.
- short sNumSteps) // Number of steps to fades; see above.
- {
- short sRes = 0; // Assume success.
- if (ms_lBitsPerSec != 0)
- {
- // Clean up any existing memory.
- CleanUp();
- // If bits per sample is value that indicates signage . . .
- switch (ms_lBitsPerSample)
- {
- case 8:
- {
- ms_pu8Fade = (U8*)malloc((long)sNumSteps * 256L * sizeof(S16));
- if (ms_pu8Fade != NULL)
- {
- short sStep;
- short sSample;
- float fStep = 1.0F / (float)sNumSteps;
- float fCurDecimation = fStep;
- U8* pu8 = ms_pu8Fade;
- for (sStep = 0; sStep < sNumSteps; sStep++)
- {
- for (sSample = 0; sSample < 256; sSample++)
- {
- *pu8++ = (U8)( (float)(sSample - 0x80) * fCurDecimation) + 0x80;
- }
-
- fCurDecimation += fStep;
- }
- // Success.
- ms_sNumFadeSteps = sNumSteps;
- static short sSetUpAtExit = FALSE; // Remember if we already did this.
- // If we haven't already set up the at exit function . . .
- if (sSetUpAtExit == FALSE)
- {
- // Set up atexit to deallocate memory.
- atexit(CleanUp);
- sSetUpAtExit = TRUE;
- }
- }
- else
- {
- TRACE("SetFadeAccuracy(): Failed to allocate fade lookup table.\n");
- sRes = -1;
- }
- break;
- }
- case 16:
- {
- ms_ps16Fade = (S16*)malloc((long)sNumSteps * 256L * sizeof(S16));
- if (ms_ps16Fade != NULL)
- {
- short sStep;
- short sSample;
- float fStep = 1.0F / (float)sNumSteps;
- float fCurDecimation = fStep;
- S16* ps16 = ms_ps16Fade;
- for (sStep = 0; sStep < sNumSteps; sStep++)
- {
- for (sSample = 0; sSample < 256; sSample++)
- {
- *ps16++ = (S16)( (float)((sSample - 128) << 8) * fCurDecimation);
- }
-
- fCurDecimation += fStep;
- }
- // Success.
- ms_sNumFadeSteps = sNumSteps;
- static short sSetUpAtExit = FALSE; // Remember if we already did this.
- // If we haven't already set up the at exit function . . .
- if (sSetUpAtExit == FALSE)
- {
- // Set up atexit to deallocate memory.
- atexit(CleanUp);
- sSetUpAtExit = TRUE;
- }
- }
- else
- {
- TRACE("SetFadeAccuracy(): Failed to allocate fade lookup table.\n");
- sRes = -1;
- }
- break;
- }
-
- default:
- TRACE("SetFadeAccuracy(): %ld bits per sample not supported.\n", ms_lBitsPerSample);
- break;
- }
- }
- else
- {
- TRACE("SetFadeAccuracy(): No data type set. Use SetDataType().\n");
- sRes = 1;
- }
- return sRes;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Set type of PCM data in use. This will reset all effects.
- // (static).
- //
- //////////////////////////////////////////////////////////////////////////////
- void RSndFx::SetDataType( // Returns nothing.
- long lSamplesPerSec, // Samples per second.
- long lBitsPerSample, // Bits per sample.
- long lNumChannels) // Number of channels.
- {
- ms_lSamplesPerSec = lSamplesPerSec;
- ms_lBitsPerSample = lBitsPerSample;
- ms_lNumChannels = lNumChannels;
- // Precalculate bits per second to aid in computation time.
- ms_lBitsPerSec = lSamplesPerSec * lBitsPerSample * lNumChannels;
- }
- /////////////////////////////////////////////////////////////////////////
- //
- // Fades in lNumBytes of pnData for signed TYPE.
- //
- /////////////////////////////////////////////////////////////////////////
- template <
- class TYPE> // Data type, signed.
- inline void Decimate( // Returns nothing.
- TYPE* psnSrcData, // Data buffer to decimate.
- TYPE* psnDstData, // Decimation destination.
- long lNumBytes, // Number of bytes in buffer.
- TYPE* psnTable) // Attenuation table.
- {
- long lNumSamples = lNumBytes / sizeof(TYPE);
- while (lNumSamples-- > 0)
- {
- *psnDstData++ = psnTable[((*psnSrcData++ + 0x0080) >> 8) + 128];
- }
- }
- /////////////////////////////////////////////////////////////////////////
- //
- // Fades in lNumBytes of punData for unsigned UTYPE.
- //
- /////////////////////////////////////////////////////////////////////////
- template <
- class UTYPE> // Data type, unsigned.
- inline void UnsignedDecimate( // Returns nothing.
- UTYPE* punSrcData, // Data buffer to decimate.
- UTYPE* punDstData, // Decimation destination.
- long lNumBytes, // Number of bytes in buffer.
- UTYPE* punTable) // Attenuation table.
- {
- long lNumSamples = lNumBytes / sizeof(UTYPE);
- while (lNumSamples-- > 0)
- {
- *punDstData++ = punTable[*punSrcData++];
- }
- }
- /////////////////////////////////////////////////////////////////////////
- //
- // Implements the effect on the provided buffer.
- //
- /////////////////////////////////////////////////////////////////////////
- void RSndFx::Do( // Returns nothing.
- UCHAR* pucSrcData, // Data to affect.
- long lBufSize, // Amount of data.
- UCHAR* pucDstData /*= NULL*/) // Destination for data, defaults
- // to same as source.
- {
- if (ms_lBitsPerSec > 0)
- {
- // If any active effects . . .
- if (m_fx != 0)
- {
- // If there is no destination . . .
- if (pucDstData == NULL)
- {
- pucDstData = pucSrcData;
- }
- if (m_fx & FadeIn)
- {
- if (m_lFadeInBytesDurationAffected < m_lFadeInBytesDuration)
- {
- switch (ms_lBitsPerSample)
- {
- case 8:
- {
- UnsignedDecimate( // Returns nothing.
- (U8*)pucSrcData, // Data buffer to fade.
- (U8*)pucDstData, // Dest data buffer.
- lBufSize, // Number of bytes in buffer.
- ms_pu8Fade + (m_lFadeInBytesDurationAffected / m_lFadeInRate) * 256 ); // Attenuation Table.
- break;
- }
- case 16:
- {
- Decimate( // Returns nothing.
- (S16*)pucSrcData, // Data buffer to fade.
- (S16*)pucDstData, // Dest data buffer.
- lBufSize, // Number of bytes in buffer.
- ms_ps16Fade + (m_lFadeInBytesDurationAffected / m_lFadeInRate) * 256 ); // Attenuation Table.
- break;
- }
- default:
- {
- TRACE("Do(): Unsupported bits per sample.\n");
- break;
- }
- }
- m_lFadeInBytesDurationAffected += lBufSize;
- }
- else
- {
- // Done.
- ActivateFadeIn(FALSE);
- }
- }
- else
- {
- if (m_fx & FadeOut)
- {
- if (m_lFadeOutBytesDurationRemaining > 0)
- {
- switch (ms_lBitsPerSample)
- {
- case 8:
- {
- UnsignedDecimate( // Returns nothing.
- (U8*)pucSrcData, // Data buffer to fade.
- (U8*)pucDstData, // Dest data buffer.
- lBufSize, // Number of bytes in buffer.
- ms_pu8Fade + (m_lFadeOutBytesDurationRemaining / m_lFadeOutRate) * 256 ); // Attenuation Table.
- break;
- }
- case 16:
- {
- Decimate( // Returns nothing.
- (S16*)pucSrcData, // Data buffer to fade.
- (S16*)pucDstData, // Dest data buffer.
- lBufSize, // Number of bytes in buffer.
- ms_ps16Fade + (m_lFadeOutBytesDurationRemaining / m_lFadeOutRate) * 256 ); // Attenuation table.
- break;
- }
- default:
- {
- TRACE("Do(): Unsupported bits per sample.\n");
- break;
- }
- }
- m_lFadeOutBytesDurationRemaining -= lBufSize;
- }
- else
- {
- // Done.
- ActivateFadeOut(FALSE);
- }
- }
- }
- }
- }
- else
- {
- TRACE("Do(): Called, but no data format set. Use SetDataType().\n");
- }
- }
-
- /////////////////////////////////////////////////////////////////////////
- // Various FX.
- /////////////////////////////////////////////////////////////////////////
- //////////////////////////// Fade In ////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////
- //
- // Set up a fade in.
- //
- /////////////////////////////////////////////////////////////////////////
- short RSndFx::SetUpFadeIn( // Returns 0 on success.
- long lDuration) // Duration until silence in milliseconds.
- {
- short sRes = 0; // Assume success.
- // Must set data type before setting up effect . . .
- if (ms_lBitsPerSec > 0)
- {
- if (lDuration > 0)
- {
- m_lFadeInMillisecondsDuration = lDuration;
- m_lFadeInBytesDurationAffected = 0;
- m_lFadeInBytesDuration = MS2BYTES(m_lFadeInMillisecondsDuration);
- // Determine the number of bytes per table index.
- m_lFadeInRate = m_lFadeInBytesDuration / ms_sNumFadeSteps;
- }
- }
- else
- {
- TRACE("FadeIn(): Data type not set. Use SetDataType().\n");
- sRes = 1;
- }
- return sRes;
- }
- /////////////////////////////////////////////////////////////////////////
- //
- // Activate/Deactivate fade in.
- //
- /////////////////////////////////////////////////////////////////////////
- void RSndFx::ActivateFadeIn( // Returns nothing.
- short sActivate) // TRUE to activate, FALSE to deactivate.
- {
- if (sActivate == FALSE)
- {
- m_fx = (FX)(m_fx & (~FadeIn));
- }
- else
- {
- m_fx = (FX)(m_fx | FadeIn);
- }
- }
- /////////////////////// Fade Out ////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////
- //
- // Set up a fade out.
- //
- /////////////////////////////////////////////////////////////////////////
- short RSndFx::SetUpFadeOut( // Returns 0 on success.
- long lDuration) // Duration until full volume in milliseconds.
- {
- short sRes = 0; // Assume success.
- // Must set data type before setting up effect . . .
- if (ms_lBitsPerSec > 0)
- {
- if (lDuration > 0)
- {
- m_lFadeOutMillisecondsDuration = lDuration;
- m_lFadeOutBytesDurationRemaining = MS2BYTES(m_lFadeOutMillisecondsDuration);
- m_lFadeOutBytesDuration = m_lFadeOutBytesDurationRemaining;
- // Determine the number of bytes per table index.
- m_lFadeOutRate = m_lFadeOutBytesDuration / ms_sNumFadeSteps;
- }
- }
- else
- {
- TRACE("FadeOut(): Data type not set. Use SetDataType().\n");
- sRes = 1;
- }
- return sRes;
- }
- /////////////////////////////////////////////////////////////////////////
- //
- // Activate/Deactivate fade out.
- //
- /////////////////////////////////////////////////////////////////////////
- void RSndFx::ActivateFadeOut( // Returns nothing.
- short sActivate) // TRUE to activate, FALSE to deactivate.
- {
- if (sActivate != FALSE)
- {
- // Deactivates fade ins.
- ActivateFadeIn(FALSE);
- m_fx = (FX)(m_fx | FadeOut);
- }
- else
- {
- m_fx = (FX)(m_fx & (~FadeOut));
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- // EOF
- //////////////////////////////////////////////////////////////////////////////
|