From: <fea...@li...> - 2006-03-09 18:17:58
|
Revision: 61 Author: alex_lerch Date: 2006-03-09 10:17:39 -0800 (Thu, 09 Mar 2006) ViewCVS: http://svn.sourceforge.net/feapi/?rev=61&view=rev Log Message: ----------- added zerocrossings example plugin Modified Paths: -------------- trunk/FEAPI/build/Win/FEAPI.dsw Added Paths: ----------- trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ExamplePluginZeroCrossings.def trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ExamplePluginZeroCrossings.dsp trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/ trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/FEAPIExamplePluginZeroCrossings.cpp trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/FEAPIExamplePluginZeroCrossings.h trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/RingBuffer.h trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/fft.h trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/zplFFTGen.cpp trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/zplFFTGenCore.cpp trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/zplFFT_If.cpp trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/zplVecLib.h trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/zplVecLibDispatch.cpp trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/zplVecLibGen.cpp Added: trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ExamplePluginZeroCrossings.def =================================================================== --- trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ExamplePluginZeroCrossings.def (rev 0) +++ trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ExamplePluginZeroCrossings.def 2006-03-09 18:17:39 UTC (rev 61) @@ -0,0 +1,102 @@ +;//////////////////////////////////////////////////////////////////////////////////// +;// /*! \file FEAPI.def: \brief declares the module parameters +;// for the DLL */ +;// +;// Copyright (c) 2004-2005, Alexander Lerch, zplane.development GbR +;// All rights reserved. +;// +;// Redistribution and use in source and binary forms, with or without +;// modification, are permitted provided that the following conditions +;// are met: +;// +;// * Redistributions of source code must retain the above copyright +;// notice, this list of conditions and the following disclaimer. +;// * Redistributions in binary form must link to the feapi website +;// http://www.sf.net/projects/feapi, +;// reproduce this list of conditions and the following +;// disclaimer in the documentation and/or other materials +;// provided with the distribution. +;// * The name of the contributors to this software must not be used +;// to endorse or promote products derived from this software +;// without specific prior written permission. +;// +;// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +;// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +;// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +;// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +;// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +;// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +;// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +;// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +;// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +;// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +;// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +;// POSSIBILITY OF SUCH DAMAGE. +;// +;//////////////////////////////////////////////////////////////////////////////////// +;// CVS INFORMATION +;// +;// $RCSfile$ +;// $Author: KoenTanghe $ +;// $Date: 2006-03-08 14:59:10 +0100 (Mi, 08 Mrz 2006) $ +;// +;// $Log$ +;// Revision 1.1.2.1 2006/01/19 13:52:07 remymuller +;// directory reorganization +;// +;// Revision 1.2 2005/05/20 17:09:21 alex_lerch +;// - changed function PluginCanDo to PluginGetProperty and changed the function itself to return values instead of bools +;// - cosmetic changes +;// +;// Revision 1.1.1.1 2005/03/30 14:54:40 alex_lerch +;// first draft version requiring several updates: +;// - interface check +;// - check of plugin base class +;// - implementation of host base class +;// - update of outdated documentation +;// +;// Revision 1.1 2004/11/12 20:54:28 lerch +;// - added example feature FindAbsoluteMax +;// +;// +;// +;//////////////////////////////////////////////////////////////////////////////////// + +LIBRARY "ZeroCrossings" +DESCRIPTION 'FEAPI FEAPI Example PlugIn' + +EXPORTS + ; Explicit exports can go here + FEAPI_CreatePluginInstance @01 + FEAPI_DestroyPluginInstance @02 + FEAPI_GetPluginAPIVersion @03 + FEAPI_InitializePlugin @04 + + FEAPI_GetPluginProperty @11 + FEAPI_GetPluginName @12 + FEAPI_GetPluginVendor @13 + FEAPI_GetPluginVendorVersion @14 + FEAPI_GetPluginDescription @15 + FEAPI_GetPluginCopyright @16 + FEAPI_GetPluginId @17 + + FEAPI_GetPluginNumOfInputs @21 + FEAPI_GetPluginInputDescription @22 + + FEAPI_GetPluginNumOfParameters @31 + FEAPI_GetPluginParameterDescription @32 + FEAPI_SetPluginParameter @33 + FEAPI_GetPluginParameter @34 + + FEAPI_GetPluginNumOfResults @41 + FEAPI_GetPluginResultDescription @42 + FEAPI_GetPluginResultLatency @43 + FEAPI_GetPluginSizeOfResult @44 + FEAPI_GetPluginResult @45 + + FEAPI_ProcessPlugin @51 + FEAPI_ProcessPluginDone @52 + + FEAPI_ResetPlugin @61 + + Added: trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ExamplePluginZeroCrossings.dsp =================================================================== --- trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ExamplePluginZeroCrossings.dsp (rev 0) +++ trunk/FEAPI/build/Win/ExamplePluginZeroCrossings/ExamplePluginZeroCrossings.dsp 2006-03-09 18:17:39 UTC (rev 61) @@ -0,0 +1,192 @@ +# Microsoft Developer Studio Project File - Name="ZeroCrossings" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ZeroCrossings - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ExamplePluginZeroCrossings.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ExamplePluginZeroCrossings.mak" CFG="ZeroCrossings - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ZeroCrossings - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ZeroCrossings - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ZeroCrossings - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../lib" +# PROP Intermediate_Dir "../../../tmp/" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /Ob2 /I "../../../include" /I "../../../sdk/plugin/include" /I "../../../examples/plugin/FEAPIExamplePluginZeroCrossings" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /out:"../../../bin/ZeroCrossings.dll" + +!ELSEIF "$(CFG)" == "ZeroCrossings - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../lib/Debug" +# PROP Intermediate_Dir "../../../tmp/Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../../include" /I "../../../sdk/plugin/include" /I "../../../examples/plugin/FEAPIExamplePluginZeroCrossings" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../../bin/Debug/ZeroCrossings.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "ZeroCrossings - Win32 Release" +# Name "ZeroCrossings - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\FEAPIExamplePluginZeroCrossings.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\zplFFT_If.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\zplFFTGen.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\zplFFTGenCore.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\zplVecLibDispatch.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\zplVecLibGen.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\FEAPIExamplePluginZeroCrossings.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\fft.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\RingBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\examples\plugin\FEAPIExamplePluginZeroCrossings\zplVecLib.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Definition Files" + +# PROP Default_Filter "def" +# Begin Source File + +SOURCE=.\ExamplePluginZeroCrossings.def +# End Source File +# End Group +# Begin Group "FEAPI" + +# PROP Default_Filter "" +# Begin Group "sdk" + +# PROP Default_Filter "" +# Begin Group "src" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\sdk\plugin\src\FEAPIPluginBase.cpp +# End Source File +# End Group +# Begin Group "include" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\sdk\plugin\include\FEAPIEntryPoints.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\sdk\plugin\include\FEAPIPluginBase.h +# End Source File +# End Group +# End Group +# End Group +# Begin Group "Documentation Files" + +# PROP Default_Filter ".txt" +# Begin Source File + +SOURCE=..\..\..\doc\docugenPlug.txt +# End Source File +# Begin Source File + +SOURCE=..\..\..\license\license.txt +# End Source File +# End Group +# End Target +# End Project Modified: trunk/FEAPI/build/Win/FEAPI.dsw =================================================================== (Binary files differ) Added: trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/FEAPIExamplePluginZeroCrossings.cpp =================================================================== --- trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/FEAPIExamplePluginZeroCrossings.cpp (rev 0) +++ trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/FEAPIExamplePluginZeroCrossings.cpp 2006-03-09 18:17:39 UTC (rev 61) @@ -0,0 +1,660 @@ +//////////////////////////////////////////////////////////////////////////////////// +// /*! \file FEAPIZeroCrossings.cpp: \brief implementation of the CZeroCrossings class. */ +// +// Copyright (c) 2005, Alexander Lerch, zplane.development GbR +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must link to the feapi website +// http://www.sf.net/projects/feapi, +// reproduce this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// * The name of the contributors to this software must not be used +// to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//////////////////////////////////////////////////////////////////////////////////// +// CVS INFORMATION +// +// $RCSfile$ +// $Author$ +// $Date$ +// +// $Log$ +// +//////////////////////////////////////////////////////////////////////////////////// + + + +#include <string> +#include <iostream> +#include <math.h> + +#include "zplVecLib.h" + +#include "FEAPI.h" +#include "FEAPIExamplePluginZeroCrossings.h" + +#ifndef FLT_MAX +#define FLT_MAX 3.402823466e+38F +#endif + +#define kDefaultNumOfResults 8 + +/*! this defines the version of the PlugIn itself */ +#define _MY_MAJOR_VERSION 0x00000000 +#define _MY_MINOR_VERSION 0x00000000 +#define _MY_SUB_VERSION 0x00000001 + + +// defines for plug in name etc. +#define _MY_PLUGIN_NAME "ZeroCrossings" +#define _MY_PLUGIN_VENDOR "zplane.development" +#define _MY_PLUGIN_DESCRIPTION "This PlugIn calculates the relative number of zero crossings per channel. A zero crossing is a sign change of two neibourghed samples." +#define _MY_PLUGIN_COPYRIGHT "(c) 2005 by zplane.development" +#define _MY_PLUGIN_ID "zplZeroCrossings" + + +// defines for description of result +#define kFeatureName "Relative number of Zero-Crossings" +#define kFeatureUnit "-" +#define kFeatureDescription "The number of zero crossings in the analysis block divided by the analysis block length" +#define kFeatureRangeMin 0.0F +#define kFeatureRangeMax 1.0F +#define kFeatureIsQuantized -1 // value is not quantized + +#define kParam1Name "Analysis Block Length" +#define kParam1Unit "Frames" +#define kParam1Description "Length of analysis window for one result" +#define kParam1RangeMin 4 +#define kParam1RangeMax (float)((1<<30)-1) +#define kParam1DefaultValue 1024 +#define kParam1QuantizedTo 4 +#define kParam1IsChangeableInRealTime false + +#define kParam2Name "Analysis Hop-Size" +#define kParam2Unit "ms" +#define kParam2Description "Distance between two analysis block beginnings" +#define kParam2RangeMin 1 +#define kParam2RangeMax (float)((1<<30)-1) +#define kParam2DefaultValue 10 +#define kParam2QuantizedTo -1 +#define kParam2IsChangeableInRealTime false + +#define kParam3Name "Individual Channels or Sum Channel" +#define kParam3Unit "" +#define kParam3Description "Determines wether the calculation should be done on the sum of all input channels ('0') or on each individual channel ('1')" +#define kParam3RangeMin 0 +#define kParam3RangeMax 1 +#define kParam3DefaultValue 0 +#define kParam3QuantizedTo 1 +#define kParam3IsChangeableInRealTime false + +enum MyParameters_t +{ + kBlockSize = 0, + kHopSize = 1, + kChannelMode = 2, + + kNumParameters +}; + +_THE_PLUGIN_CLASS::_THE_PLUGIN_CLASS () : CFeatureExtractBase() +{ + + zplVecLibDispatcher (); + + m_ppCRingBuffer = 0; + m_ppResults = 0; + m_pfProcessBuffer = 0; + m_ptLocalTimeStamp = 0; + + m_iNumberOfParameters = kNumParameters; + m_iSizeOfResultBuffer = kDefaultNumOfResults; + + // set strings that will be returned by the default methods + m_cPluginName = _MY_PLUGIN_NAME; + m_cPluginVendor = _MY_PLUGIN_VENDOR; + m_cPluginDescription = _MY_PLUGIN_DESCRIPTION; + m_cPluginId = _MY_PLUGIN_ID; + m_cPluginCopyRight = _MY_PLUGIN_COPYRIGHT; + + // set plug in version info + m_iMajorVersion = _MY_MAJOR_VERSION; + m_iMinorVersion = _MY_MINOR_VERSION; + m_iSubVersion = _MY_SUB_VERSION; + + m_afParameters[kBlockSize] = kParam1DefaultValue; + m_afParameters[kHopSize] = kParam2DefaultValue; + m_afParameters[kChannelMode]= kParam3DefaultValue; +} + + +_THE_PLUGIN_CLASS::~_THE_PLUGIN_CLASS () +{ + int iCh; + if (m_ppCRingBuffer) + { + for (iCh = 0; iCh < m_iNumberOfChannels; iCh++) + { + if (m_ppCRingBuffer[iCh]) + delete m_ppCRingBuffer[iCh]; + m_ppCRingBuffer[iCh] = 0; + } + delete [] m_ppCRingBuffer; + m_ppCRingBuffer = 0; + } + if (m_ppResults) + { + for (iCh = 0; iCh < m_iNumberOfResults; iCh++) + { + if (m_ppResults[iCh]) + delete [] m_ppResults[iCh]; + m_ppResults[iCh] = 0; + } + delete [] m_ppResults; + m_ppResults = 0; + } + if (m_ptLocalTimeStamp) + delete [] m_ptLocalTimeStamp; + m_ptLocalTimeStamp = 0; + + zplfFree (m_pfProcessBuffer); +} + + +FEAPI_Error_t _THE_PLUGIN_CLASS::InitializePlugin (float fInputSampleRate, + int iNumberOfAudioChannels, + int iHostApiMajorVersion, + FEAPI_UserData_t *pstUserData) +{ + FEAPI_Error_t rErr; + int iCh; + + // free already allocated memory + if (m_ppCRingBuffer) + { + for (iCh = 0; iCh < m_iNumberOfChannels; iCh++) + { + if (m_ppCRingBuffer[iCh]) + delete m_ppCRingBuffer[iCh]; + m_ppCRingBuffer[iCh] = 0; + } + delete [] m_ppCRingBuffer; + m_ppCRingBuffer = 0; + } + if (m_ppResults) + { + for (iCh = 0; iCh < m_iNumberOfResults; iCh++) + { + if (m_ppResults[iCh]) + delete [] m_ppResults[iCh]; + m_ppResults[iCh] = 0; + } + delete [] m_ppResults; + m_ppResults = 0; + } + if (m_ptLocalTimeStamp) + delete [] m_ptLocalTimeStamp; + m_ptLocalTimeStamp = 0; + zplfFree (m_pfProcessBuffer); + + rErr = CFeatureExtractBase::InitializePlugin ( fInputSampleRate, + iNumberOfAudioChannels, + iHostApiMajorVersion, + pstUserData); + + + if (rErr != FEAPI_kNoError) + return rErr; + + // allocate ringbuffers and memory for results and temp memory for processing + m_pfProcessBuffer = zplfMalloc ((int)(m_afParameters[kBlockSize])); + m_ptLocalTimeStamp = new FEAPI_TimeStamp_t [iNumberOfAudioChannels]; + m_ppCRingBuffer = new CRingBuffer<float>*[iNumberOfAudioChannels]; + m_ppResults = new InternalResults_t*[iNumberOfAudioChannels]; + for (iCh = 0; iCh < iNumberOfAudioChannels; iCh++) + { + m_ppCRingBuffer[iCh] = new CRingBuffer<float>((unsigned int)(m_afParameters[kBlockSize])<<1); + m_ppResults[iCh] = new InternalResults_t[m_iSizeOfResultBuffer]; + memset (m_ppResults[iCh], 0, sizeof (InternalResults_t) * m_iSizeOfResultBuffer); + } + memset (m_ptLocalTimeStamp, 0, sizeof(FEAPI_TimeStamp_t)*iNumberOfAudioChannels); + + m_iNumberOfResults = 1; + + return FEAPI_kNoError; +} + + +FEAPI_Error_t _THE_PLUGIN_CLASS::GetPluginResultDescription (int iResultIndex, FEAPI_SignalDescription_t *pstResultDescription) +{ + // the description is for all results identical in this case + // only the channel number changes (channel number equals feature number for this plugin) + + if ((iResultIndex >= m_iNumberOfResults) || (iResultIndex < 0)) + return FEAPI_kUnspecifiedError; + + strcpy (pstResultDescription->acName, kFeatureName); + strcpy (pstResultDescription->acUnit, kFeatureUnit); + strcpy (pstResultDescription->acDescription, kFeatureDescription); + pstResultDescription->fRangeMin = kFeatureRangeMin; + pstResultDescription->fRangeMax = kFeatureRangeMax; + pstResultDescription->fQuantizedTo = kFeatureIsQuantized; + pstResultDescription->fSampleRate = 0.001F / m_afParameters[kHopSize]; + + return FEAPI_kNoError; +} + + +FEAPI_Error_t _THE_PLUGIN_CLASS::GetPluginInputDescription (int iInputIndex, FEAPI_SignalDescription_t *pstInputDescription) +{ + // the description is for all inputs identical in this case + // only the channel number changes (channel number equals feature number for this plugin) + + if (iInputIndex >= m_iNumberOfChannels) + return FEAPI_kUnspecifiedError; + + std::string tmp = "Channel: "; + char actmp[100] ; + sprintf(actmp,"%d",iInputIndex); + tmp.append (actmp); + tmp.copy (pstInputDescription->acName, FEAPI_uiMaxNameLength); + + tmp.erase (0, tmp.length ()); + tmp.copy (pstInputDescription->acUnit, FEAPI_uiMaxNameLength); + + tmp.erase (0, tmp.length ()); + strcpy (pstInputDescription->acDescription, pstInputDescription->acName); + + pstInputDescription->fRangeMin = -1; + pstInputDescription->fRangeMax = 1; + pstInputDescription->fQuantizedTo = -1; + pstInputDescription->fSampleRate = m_fSampleRate; + + return FEAPI_kNoError; +} + + +FEAPI_Error_t _THE_PLUGIN_CLASS::GetPluginParameterDescription (int iParameterIndex, FEAPI_ParameterDescription_t *pstParameterDescription) +{ + if ((iParameterIndex >= m_iNumberOfParameters) || (iParameterIndex < 0)) + return FEAPI_kUnspecifiedError; + + switch (iParameterIndex) + { + case kBlockSize: + { + strcpy (pstParameterDescription->acName, kParam1Name); + strcpy (pstParameterDescription->acUnit, kParam1Unit); + strcpy (pstParameterDescription->acDescription, kParam1Description); + pstParameterDescription->fRangeMin = kParam1RangeMin; + pstParameterDescription->fRangeMax = kParam1RangeMax; + pstParameterDescription->fDefaultValue = kParam1DefaultValue; + pstParameterDescription->fQuantizedTo = kParam1QuantizedTo; + pstParameterDescription->bIsChangeableInRealTime= kParam1IsChangeableInRealTime; + break; + } + case kHopSize: + { + strcpy (pstParameterDescription->acName, kParam2Name); + strcpy (pstParameterDescription->acUnit, kParam2Unit); + strcpy (pstParameterDescription->acDescription, kParam2Description); + pstParameterDescription->fRangeMin = kParam2RangeMin; + pstParameterDescription->fRangeMax = kParam2RangeMax; + pstParameterDescription->fDefaultValue = kParam2DefaultValue; + pstParameterDescription->fQuantizedTo = kParam2QuantizedTo; + pstParameterDescription->bIsChangeableInRealTime= kParam2IsChangeableInRealTime; + break; + } + case kChannelMode: + { + strcpy (pstParameterDescription->acName, kParam3Name); + strcpy (pstParameterDescription->acUnit, kParam3Unit); + strcpy (pstParameterDescription->acDescription, kParam3Description); + pstParameterDescription->fRangeMin = kParam3RangeMin; + pstParameterDescription->fRangeMax = kParam3RangeMax; + pstParameterDescription->fDefaultValue = kParam3DefaultValue; + pstParameterDescription->fQuantizedTo = kParam3QuantizedTo; + pstParameterDescription->bIsChangeableInRealTime= kParam3IsChangeableInRealTime; + break; + } + default: + return FEAPI_kUnspecifiedError; + } + + return FEAPI_kNoError; +} + + +FEAPI_Error_t _THE_PLUGIN_CLASS::SetPluginParameter (int iParameterIndex, float fValue) +{ + float fMinValue, + fMaxValue; + + if ((iParameterIndex >= m_iNumberOfParameters) || (iParameterIndex < 0)) + return FEAPI_kUnspecifiedError; + + // check range + switch (iParameterIndex) + { + case kBlockSize: + fMinValue = kParam1RangeMin; + fMaxValue = kParam1RangeMax; + break; + case kHopSize: + fMinValue = kParam2RangeMin; + fMaxValue = kParam2RangeMax; + break; + case kChannelMode: + fMinValue = kParam3RangeMin; + fMaxValue = kParam3RangeMax; + break; + default: + return FEAPI_kUnspecifiedError; + } + + if ((fValue < fMinValue) || (fValue > fMaxValue)) + return FEAPI_kUnspecifiedError; + + m_afParameters[iParameterIndex] = fValue; + m_iNumberOfResults = (m_afParameters[kChannelMode] == 0) ? 1 : m_iNumberOfChannels; + + // since all parameters are non-realtime parameters, we can call initialize her for simplicity + this->InitializePlugin (m_fSampleRate, m_iNumberOfChannels, 1, 0); + + return FEAPI_kUnknownError; +} + + +float _THE_PLUGIN_CLASS::GetPluginParameter (int iParameterIndex) +{ + if ((iParameterIndex >= m_iNumberOfParameters) || (iParameterIndex < 0)) + return FEAPI_kUnspecifiedError; + + return m_afParameters[iParameterIndex]; +} + + +int _THE_PLUGIN_CLASS::GetPluginResultLatency (int iResultIndex) +{ + return m_afParameters[kBlockSize]; +} + + +FEAPI_Error_t _THE_PLUGIN_CLASS::ProcessPluginDone () +{ + int iNumProcessChannels = m_iNumberOfChannels, + iProcessBlockSize = (int)(m_afParameters[kBlockSize]), + iSamplesInBuffer = m_ppCRingBuffer[0]->GetSamplesInBuffer (); + + for (int iCh = 0; iCh < iNumProcessChannels; iCh++) + { + int iTempResult = 0; + + m_ppCRingBuffer[iCh]->GetPostInc (m_pfProcessBuffer, iSamplesInBuffer); + memset (&m_pfProcessBuffer[iSamplesInBuffer], 0, sizeof(float)*(iProcessBlockSize - iSamplesInBuffer)); + + iTempResult = zplfZeroCrossings (m_pfProcessBuffer, iProcessBlockSize); + + m_ptLocalTimeStamp[iCh] = m_ptLocalTimeStamp[iCh] + m_afParameters[kHopSize]*0.001F; + this->WriteResult (iCh, iTempResult * 1.0F / iSamplesInBuffer, m_ptLocalTimeStamp[iCh]); + } + + return FEAPI_kNoError; +} + +FEAPI_Error_t _THE_PLUGIN_CLASS::ProcessPlugin (const float **ppfInputBuffer, const FEAPI_TimeStamp_t *ptTimeStamps, int iNumberOfFrames) +{ + bool bDownmixToMono = (m_afParameters[kChannelMode] == 0)? true : false; + int iCh, + iIdx, + iProcessBlockSize = (int)(m_afParameters[kBlockSize]), + iHopSize = (int)(m_afParameters[kHopSize]*0.001F * m_fSampleRate + .5F), + iNumFramesLeft = iNumberOfFrames, + iNumProcessChannels = m_iNumberOfChannels, + iSamplesInBuffer = 0; + + if (!m_bIsInitialized) + return FEAPI_kUnspecifiedError; + + // do time stamp handling, in both cases: no/defined time stamp + if (ptTimeStamps) + { + for (iCh = 0; iCh < m_iNumberOfChannels; iCh++) + m_ptLocalTimeStamp[iCh] = ptTimeStamps[iCh] + iNumberOfFrames/m_fSampleRate; + } + else + { + for (iCh = 0; iCh < m_iNumberOfChannels; iCh++) + m_ptLocalTimeStamp[iCh] += iNumberOfFrames/m_fSampleRate; + } + + // if there are sufficient frames to process, do it! + while (m_ppCRingBuffer[0]->GetSamplesInBuffer () + iNumFramesLeft >= iProcessBlockSize) + { + // check if we have to downmix to mono or not + if (bDownmixToMono) + { + iNumProcessChannels = 1; + // downmix and write to buffer, decr numframesleft + memcpy (m_pfProcessBuffer, ppfInputBuffer[0], sizeof(float) * iHopSize); + for (iCh = 1; iCh < m_iNumberOfChannels; iCh++) + { + const float *pfBuffer = &ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft]; + + for (iIdx = 0; iIdx < iHopSize; iIdx++) + m_pfProcessBuffer[iIdx] += pfBuffer[iIdx]; + + // just a comment: scaling does not have any influence on zero crossings... + } + m_ppCRingBuffer[0]->PutPostInc (m_pfProcessBuffer, iHopSize); + } + else + { + for (iCh = 0; iCh < m_iNumberOfChannels; iCh++) + m_ppCRingBuffer[iCh]->PutPostInc (&ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft], iHopSize); + } + + // decrement number of frames left in ppfInputBuffer + iNumFramesLeft -= iHopSize; + + // get the current number of sample in ring buffer + iSamplesInBuffer = m_ppCRingBuffer[0]->GetSamplesInBuffer (); + + // if there are not enough sample in ring buffer, go on (note that this is not really possible...) + if (iSamplesInBuffer < iProcessBlockSize) + continue; + + // now do the processing + for (iCh = 0; iCh < iNumProcessChannels; iCh++) + { + int iTempResult = 0; + + // get data from ring bufffer and oncrement read pointer + m_ppCRingBuffer[iCh]->GetOff (m_pfProcessBuffer, iProcessBlockSize, 0); + m_ppCRingBuffer[iCh]->SetReadPos (m_ppCRingBuffer[iCh]->GetReadPos () + iHopSize); + + // calculation the number of zero crossings: pseudo: length(find((a(1:iBlockSize-1).*a(0:iBlockSize-2)) < 0)) + iTempResult = zplfZeroCrossings (m_pfProcessBuffer, iProcessBlockSize); + + // adjust time stamp and write result to output buffer + m_ptLocalTimeStamp[iCh] = m_ptLocalTimeStamp[iCh] - iSamplesInBuffer/m_fSampleRate; + this->WriteResult (iCh, iTempResult * 1.0F / iProcessBlockSize, m_ptLocalTimeStamp[iCh]); + } + } + + // if there are frames left in ppfInputBuffer, handle them here + if (iNumFramesLeft > 0) + { + // write remaining frames to ringbuffer (distinguish downmix or not..., decr numframesleft) + if (bDownmixToMono) + { + // downmix and write to buffer + memcpy (m_pfProcessBuffer, ppfInputBuffer[0], sizeof(float) * iHopSize); + for (iCh = 1; iCh < m_iNumberOfChannels; iCh++) + { + const float *pfBuffer = &ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft]; + + for (iIdx = 0; iIdx < iNumFramesLeft; iIdx++) + m_pfProcessBuffer[iIdx] += pfBuffer[iIdx]; + } + m_ppCRingBuffer[0]->PutPostInc (m_pfProcessBuffer, iNumFramesLeft); + } + else + { + for (iCh = 0; iCh < m_iNumberOfChannels; iCh++) + m_ppCRingBuffer[iCh]->PutPostInc (&ppfInputBuffer[iCh][iNumberOfFrames - iNumFramesLeft], iHopSize); + } + } + + return FEAPI_kNoError; +} + +int _THE_PLUGIN_CLASS::GetPluginSizeOfResult (int iResultIndex) +{ + if ((iResultIndex >= m_iNumberOfResults) || (iResultIndex < 0)) + return -1; + + if (m_ppResults[iResultIndex][0].bHoldsResult == true) + return 1; + else + return 0; +} + + +FEAPI_Error_t _THE_PLUGIN_CLASS::GetPluginResult (int iResultIndex, float *pfResult, FEAPI_TimeStamp_t *ptTimeStamp) +{ + if ((iResultIndex >= m_iNumberOfResults) || (iResultIndex < 0)) + return FEAPI_kUnspecifiedError; + + if (m_ppResults[iResultIndex][0].bHoldsResult == false) + return FEAPI_kUnspecifiedError; + + pfResult[0] = m_ppResults[iResultIndex][0].fResult; + ptTimeStamp[0] = m_ppResults[iResultIndex][0].tTimeStamp; + + memmove (&m_ppResults[iResultIndex][0], &m_ppResults[iResultIndex][1], (m_iSizeOfResultBuffer - 1)*sizeof(InternalResults_t)); + m_ppResults[iResultIndex][m_iSizeOfResultBuffer-1].bHoldsResult = false; + + return FEAPI_kNoError; +} + + +FEAPI_Error_t _THE_PLUGIN_CLASS::ResetPlugin () +{ + for (int iCh = 0; iCh < m_iNumberOfChannels; iCh++) + { + m_ppCRingBuffer[iCh]->Reset (); + m_ptLocalTimeStamp[iCh] = 0; + } + return FEAPI_kNoError; +} + + +float _THE_PLUGIN_CLASS::GetPluginProperty ( FEAPI_PluginProperty_t ePluginProperty) +{ + switch (ePluginProperty) + { + case FEAPI_kMinSampleRate: + { + return 1; + } + case FEAPI_kMaxSampleRate: + { + return 1e38F; + } + case FEAPI_kMinChannels: + { + return 1; + } + case FEAPI_kMaxChannels: + { + return (float)((1<<30)-1); + } + case FEAPI_kMinFrameSize: + { + return 1; + } + case FEAPI_kMaxFrameSize: + { + return (float)((1<<30)-1); + } + case FEAPI_kOptFrameSize: + { + return (int)(m_afParameters[kHopSize] * 0.001F * m_fSampleRate + .5F); + } + default: + { + // this shall never happen ... + return -1; + } + } + return -1; +} + +void CZeroCrossings::WriteResult (int iResultIdx, float fValue, FEAPI_TimeStamp_t tTimeStamp) +{ + int iCurrentIdx = 0; + + for (iCurrentIdx = 0; iCurrentIdx < m_iSizeOfResultBuffer; iCurrentIdx++) + { + ZASSERT (!m_ppResults[iCurrentIdx]); + if (m_ppResults[iResultIdx][iCurrentIdx].bHoldsResult == false) + break; + } + if (iCurrentIdx == m_iSizeOfResultBuffer) + { + // alloc new memory + m_iSizeOfResultBuffer <<= 1; + for (int i = 0; i < m_iNumberOfResults; i++) + { + InternalResults_t *pTmp = new InternalResults_t[m_iSizeOfResultBuffer]; + memcpy (pTmp, m_ppResults[i], (m_iSizeOfResultBuffer>>1) * sizeof(InternalResults_t)); + memset (&pTmp[(m_iSizeOfResultBuffer>>1)], 0, (m_iSizeOfResultBuffer>>1) * sizeof(InternalResults_t)); + delete [] m_ppResults[i]; + m_ppResults[i] = 0; + m_ppResults[i] = pTmp; + } + } + + m_ppResults[iResultIdx][iCurrentIdx].bHoldsResult = true; + m_ppResults[iResultIdx][iCurrentIdx].fResult = fValue; + m_ppResults[iResultIdx][iCurrentIdx].tTimeStamp = tTimeStamp; + + return; +} + +/////////////////////////////////////// +// entry points +#include "FEAPIEntryPoints.h" + +#ifdef __cplusplus +extern "C" { +#endif + +FEAPI_ENTRY_POINTS(CZeroCrossings) + +#ifdef __cplusplus +} +#endif +/////////////////////////////////////// Added: trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/FEAPIExamplePluginZeroCrossings.h =================================================================== --- trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/FEAPIExamplePluginZeroCrossings.h (rev 0) +++ trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/FEAPIExamplePluginZeroCrossings.h 2006-03-09 18:17:39 UTC (rev 61) @@ -0,0 +1,141 @@ +//////////////////////////////////////////////////////////////////////////////////// +// /*! \file FEAPIZeroCrossings.h: \brief interface of the CZeroCrossings class. */ +// +// Copyright (c) 2005, Alexander Lerch, zplane.development GbR +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must link to the feapi website +// http://www.sf.net/projects/feapi, +// reproduce this list of conditions and the following +// disclaimer in the documentation and/or other materials +// provided with the distribution. +// * The name of the contributors to this software must not be used +// to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//////////////////////////////////////////////////////////////////////////////////// +// CVS INFORMATION +// +// $RCSfile$ +// $Author$ +// $Date$ +// +// $Log$ +// +//////////////////////////////////////////////////////////////////////////////////// + +#if !defined(ZERO_CROSSINGS_HEADER_INCLUDED__) +#define ZERO_CROSSINGS_HEADER_INCLUDED__ + + +#include "FEAPIPluginBase.h" + +#define _THE_PLUGIN_CLASS CZeroCrossings // change this class name to your class + +template <class T> class CRingBuffer; + +/*! +*/ +class _THE_PLUGIN_CLASS : public CFeatureExtractBase +{ +public: + + _THE_PLUGIN_CLASS (); + + virtual ~_THE_PLUGIN_CLASS (); + + + //////////////////////////////////////////////////////////////////////////////////////// + // method declaration + // if you do not intend to use some of these functions, just delete them and the default + // values will be returned + + FEAPI_Error_t GetPluginResultDescription ( int iResultIndex, + FEAPI_SignalDescription_t *pstResultDescription); + + FEAPI_Error_t GetPluginInputDescription ( int iInputIndex, + FEAPI_SignalDescription_t *pstInputDescription); + + FEAPI_Error_t GetPluginParameterDescription ( int iParameterIndex, + FEAPI_ParameterDescription_t *pstParameterDescription); + + FEAPI_Error_t SetPluginParameter ( int iParameterIndex, + float fValue); + + float GetPluginParameter ( int iParameterIndex); + + + int GetPluginResultLatency (int iResultIndex); + + float GetPluginProperty ( FEAPI_PluginProperty_t ePluginProperty); + + FEAPI_Error_t InitializePlugin ( float fInputSampleRate, + int iNumberOfAudioChannels, + int iHostApiMajorVersion, + FEAPI_UserData_t *pstUserData); + + FEAPI_Error_t ProcessPlugin ( const float **ppfInputBuffer, + const FEAPI_TimeStamp_t *ptFEAPI_TimeStamp, + int iNumberOfFrames); + + FEAPI_Error_t ProcessPluginDone (); + + + int GetPluginSizeOfResult (int iResultIndex); + + FEAPI_Error_t GetPluginResult ( int iResultIndex, + float *pfResult, + FEAPI_TimeStamp_t *ptFEAPI_TimeStamp); + + + FEAPI_Error_t ResetPlugin (); + +private: + + struct InternalResults_t + { + bool bHoldsResult; + float fResult; + FEAPI_TimeStamp_t tTimeStamp; + }; + + void WriteResult (int iResultIdx, float fValue, FEAPI_TimeStamp_t tTimStamp); + + // remove and add variables acc. your needs + FEAPI_SignalDescription_t m_stResultDescription; + FEAPI_TimeStamp_t *m_ptLocalTimeStamp; + + + float m_afParameters[3], + *m_pfProcessBuffer; + + CRingBuffer<float> **m_ppCRingBuffer; + + InternalResults_t **m_ppResults; + + int m_iSizeOfResultBuffer; +}; + +#endif // #if !defined(ZERO_CROSSINGS_HEADER_INCLUDED__) + + + Added: trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/RingBuffer.h =================================================================== --- trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/RingBuffer.h (rev 0) +++ trunk/FEAPI/examples/plugin/FEAPIExamplePluginZeroCrossings/RingBuffer.h 2006-03-09 18:17:39 UTC (rev 61) @@ -0,0 +1,615 @@ +//////////////////////////////////////////////////////////////////////////////////// +// /*! \file RingBuffer.h: \brief interface of the CRingBuffer class. */ +// +// Copyright (c) 2003-2005 +// zplane.development +// Flohrer Lerch Schwerdtfeger GbR +// +// CONFIDENTIALITY: +// +// This file is the property of zplane.development. +// It contains information that is regarded as privilege +// and confidential by zplane.development. +// It may not be publicly disclosed or communicated in any way without +// prior written authorization by zplane.development. +// It cannot be copied, used, or modified without obtaining +// an authorization from zplane.development. +// If such an authorization is provided, any modified version or +// copy of the software has to contain this header. +// +// WARRANTIES: +// This software is provided as << is >>, zplane.development +// makes no warranty express or implied with respect to this software, +// its fitness for a particular purpose or its merchantability. +// In no case, shall zplane.development be liable for any +// incidental or consequential damages, including but not limited +// to lost profits. +// +// zplane.development shall be under no obligation or liability in respect of +// any infringement of statutory monopoly or intellectual property +// rights of third parties by the use of elements of such software +// and User shall in any case be entirely responsible for the use +// to which he puts such elements. +// +//////////////////////////////////////////////////////////////////////////////////// +// CVS INFORMATION +// +// $RCSfile: RingBuffer.h,v $ +// $Author: lerch $ +// $Date: 2005/07/01 13:00:19 $ +// +// $Log: RingBuffer.h,v $ +// Revision 1.4 2005/07/01 13:00:19 lerch +// - replaced inline by INLINE +// +// Revision 1.3 2005/03/02 17:02:42 lerch +// - added dispatcher as well as SSE2 functions for FFT and other functions +// !!! STILL UNTESTED !!! +// +// Revision 1.2 2005/02/11 18:43:18 lerch +// - replace INLINE with INLINE +// +// Revision 1.1 2005/02/10 20:13:44 lerch +// - !UNTESTED! +// - first generic implementation of zplane vector lib and fft class +// - some complex operations are missing yet +// - should the FFT Windows be symmetric or periodic? +// +// +// +//////////////////////////////////////////////////////////////////////////////////// + +// RingBuffer.h: interface for the CRingBuffer class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(__RINGBUFFER_HEADER_INCLUDED__) +#define __RINGBUFFER_HEADER_INCLUDED__ + +#ifdef WIN32 +#define INLINE __forceinline +#else +#define INLINE +#endif + +//!< \todo update documentation +INLINE unsigned int Int2PowTwo (int iValue) +{ + unsigned int iOrder = 0; + + while (iValue>>iOrder) + iOrder++; + + if (!(iValue%(1<<(iOrder-1)))) + iOrder--; + + return (1<<(iOrder)); +} + +//******************************************************************** +// @class: CRingBuffer <template> +// @author: Tim Flohrer +// @notes: implements a Ringbuffer +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** + +template <class T> class CRingBuffer +{ + +private: + + unsigned int m_uiReadIndex, + m_uiWriteIndex, + m_uiTmpIndex; + + unsigned int m_uiSize, + m_uiMask; + + T *m_ptBuffer; + + +public: + static int CreateInstance (CRingBuffer*& pCRingBuffer, unsigned int uiLength) + { + int rErr = _NO_ERROR; + pCRingBuffer = 0; + + // create instance + pCRingBuffer = new CRingBuffer (uiLength); + + if (pCRingBuffer == NULL) + rErr = _MEM_ALLOC_FAILED; + else if (!pCRingBuffer->m_ptBuffer) + { + rErr = _MEM_ALLOC_FAILED; + delete pCRingBuffer; + pCRingBuffer= 0; + } + + return rErr; + }; + + static int DestroyInstance (CRingBuffer*& pCRingBuffer) + { + if (!pCRingBuffer) + return _INVALID_FUNCTION_ARGS; + + delete pCRingBuffer; + pCRingBuffer = 0; + + return _NO_ERROR; + }; + +//******************************************************************** +// @method: CRingBuffer +// @parameter: unsigned int uiNewSize desired size of the ring buffer +// @result: +// @author: Tim Flohrer +// @notes: constructor of the CRingbuffer class +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** + CRingBuffer(unsigned int uiNewSize) + { +// m_uiSize = (unsigned int)pow(2,1+(int)(log(uiNewSize)/log(2))); + m_uiSize = Int2PowTwo(uiNewSize); + m_uiMask = m_uiSize-1; + m_uiReadIndex = 0; + m_uiWriteIndex = 0; + m_uiTmpIndex = 0; + m_ptBuffer = 0; + m_ptBuffer = new T[m_uiSize]; + for( int i=0; i<m_uiSize; m_ptBuffer[i++] = 0); + } + + +//******************************************************************** +// @method: ~CRingBuffer +// @parameter: +// @result: +// @author: Tim Flohrer +// @notes: destructor +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** + ~CRingBuffer() + { + if (m_ptBuffer) + delete [] m_ptBuffer; + } + + +//******************************************************************** +// @method: GetOff +// @parameter: int iIndex +// @result: T +// @author: Tim Flohrer +// @notes: gets an item at offset iIndex from the +// current read pointer, without modifying +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE T GetOff(int iIndex) + { + return m_ptBuffer[(m_uiReadIndex + iIndex + m_uiSize) & m_uiMask]; + } + +INLINE T GetOffW(int iIndex) + { + return m_ptBuffer[(m_uiWriteIndex + iIndex + m_uiSize) & m_uiMask]; + } + + +//******************************************************************** +// @method: PutOff +// @parameter: T tItem +// int iIndex +// @result: +// @author: Tim Flohrer +// @notes: puts an item at offset iIndex from the +// current write pointer, without modifying +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE void PutOff(T tItem,int iIndex) + { + m_ptBuffer[(m_uiWriteIndex + iIndex + m_uiSize) & m_uiMask] = tItem; + } + +//******************************************************************** +// @method: GetOffMod +// @parameter: int iIndex +// @result: T +// @author: Tim Flohrer +// @notes: gets an item at offset iIndex from the +// current read pointer, with modifying +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE T GetOffMod(int iIndex) + { + m_uiReadIndex = ((m_uiReadIndex + iIndex + m_uiSize) & m_uiMask); + return m_ptBuffer[ m_uiReadIndex ]; + } + + +//******************************************************************** +// @method: PutOffMod +// @parameter: T tItem +// int iIndex +// @result: +// @author: Tim Flohrer +// @notes: puts an item at offset iIndex from the +// current write pointer, with modifying +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE void PutOffMod(T tItem,int iIndex) + { + m_uiWriteIndex = (m_uiWriteIndex + iIndex + m_uiSize) & m_uiMask; + m_ptBuffer[m_uiWriteIndex] = tItem; + } + + +//******************************************************************** +// @method: Get +// @parameter: +// @result: T +// @author: Tim Flohrer +// @notes: gets an item at current read pointer +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE T Get() + { + return m_ptBuffer[ m_uiReadIndex ]; + } + + +//******************************************************************** +// @method: Put +// @parameter: T tItem +// @result: +// @author: Tim Flohrer +// @notes: puts an item at current read pointer +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE void Put(T tItem) + { + m_ptBuffer[ m_uiWriteIndex ] = tItem; + } + + +//******************************************************************** +// @method: GetPostInc +// @parameter: +// @result: T +// @author: Tim Flohrer +// @notes: gets an item at the current read pointer +// and increments the read pointer afterwards +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE T GetPostInc() + { + m_uiTmpIndex = m_uiReadIndex; + m_uiReadIndex = (m_uiReadIndex + 1) & m_uiMask; + return m_ptBuffer[ m_uiTmpIndex ]; + } + +INLINE void GetPostInc (T* ptBuffer, int iNumOfItems) + { + if (iNumOfItems <= 0) + return; + m_uiTmpIndex = m_uiReadIndex; + m_uiReadIndex = (m_uiReadIndex + iNumOfItems) & m_uiMask; + if (m_uiTmpIndex + iNumOfItems <= m_uiSize) + { + memcpy (ptBuffer, &m_ptBuffer[ m_uiTmpIndex ], sizeof(T) * iNumOfItems); + return; + } + else + { + ZASSERT (m_uiSize - m_uiTmpIndex <= 0); + ZASSERT (iNumOfItems - m_uiSize + m_uiTmpIndex <= 0); + memcpy (ptBuffer, &m_ptBuffer[ m_uiTmpIndex ], sizeof(T) * (m_uiSize - m_uiTmpIndex)); + memcpy (&ptBuffer[m_uiSize - m_uiTmpIndex], m_ptBuffer, sizeof(T) * (iNumOfItems - m_uiSize + m_uiTmpIndex)); + return; + } + } +INLINE void GetOffPostInc(T* ptBuffer, int iNumOfItems, int iIndex) + { + if (iNumOfItems <= 0) + return; + m_uiTmpIndex = ((m_uiReadIndex + iIndex + m_uiSize) & m_uiMask); + m_uiReadIndex = (m_uiReadIndex + iNumOfItems) & m_uiMask; + if (m_uiTmpIndex + iNumOfItems <= m_uiSize) + { + memcpy (ptBuffer, &m_ptBuffer[ m_uiTmpIndex ], sizeof(T) * iNumOfItems); + return; + } + else + { + ZASSERT (m_uiSize - m_uiTmpIndex <= 0); + ZASSERT (iNumOfItems - m_uiSize + m_uiTmpIndex <= 0); + memcpy (ptBuffer, &m_ptBuffer[ m_uiTmpIndex ], sizeof(T) * (m_uiSize - m_uiTmpIndex)); + memcpy (&ptBuffer[m_uiSize - m_uiTmpIndex], m_ptBuffer, sizeof(T) * (iNumOfItems - m_uiSize + m_uiTmpIndex)); + return; + } + } +INLINE void GetOff(T* ptBuffer, int iNumOfItems, int iIndex) + { + if (iNumOfItems <= 0) + return; + m_uiTmpIndex = ((m_uiReadIndex + iIndex + m_uiSize) & m_uiMask); + if (m_uiTmpIndex + iNumOfItems <= m_uiSize) + { + memcpy (ptBuffer, &m_ptBuffer[ m_uiTmpIndex ], sizeof(T) * iNumOfItems); + return; + } + else + { + ZASSERT (m_uiSize - m_uiTmpIndex <= 0); + ZASSERT (iNumOfItems - m_uiSize + m_uiTmpIndex <= 0); + memcpy (ptBuffer, &m_ptBuffer[ m_uiTmpIndex ], sizeof(T) * (m_uiSize - m_uiTmpIndex)); + memcpy (&ptBuffer[m_uiSize - m_uiTmpIndex], m_ptBuffer, sizeof(T) * (iNumOfItems - m_uiSize + m_uiTmpIndex)); + return; + } + } +INLINE void GetOffW(T* ptBuffer, int iNumOfItems, int iIndex) + { + if (iNumOfItems <= 0) + return; + m_uiTmpIndex = ((m_uiWriteIndex + iIndex + m_uiSize) & m_uiMask); + if (m_uiTmpIndex + iNumOfItems <= m_uiSize) + { + memcpy (ptBuffer, &m_ptBuffer[ m_uiTmpIndex ], sizeof(T) * iNumOfItems); + return; + } + else + { + ZASSERT (m_uiSize - m_uiTmpIndex <= 0); + ZASSERT (iNumOfItems - m_uiSize + m_uiTmpIndex <= 0); + memcpy (ptBuffer, &m_ptBuffer[ m_uiTmpIndex ], sizeof(T) * (m_uiSize - m_uiTmpIndex)); + memcpy (&ptBuffer[m_uiSize - m_uiTmpIndex], m_ptBuffer, sizeof(T) * (iNumOfItems - m_uiSize + m_uiTmpIndex)); + return; + } + } + +//******************************************************************** +// @method: PutPostInc +// @parameter: T tItem +// @result: +// @author: Tim Flohrer +// @notes: puts an item at the current read pointer +// and increments the write pointer afterwards +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE void PutPostInc(T tItem) + { + m_uiTmpIndex = m_uiWriteIndex; + m_uiWriteIndex = (m_uiWriteIndex + 1) & m_uiMask; + m_ptBuffer[ m_uiTmpIndex ] = tItem; + } + + +INLINE void PutPostInc(const T *ptItem, int iNumOfItems) + { + if (iNumOfItems <= 0) + return; + m_uiTmpIndex = m_uiWriteIndex; + m_uiWriteIndex = (m_uiWriteIndex + iNumOfItems) & m_uiMask; + if (m_uiTmpIndex + iNumOfItems <= m_uiSize) + { + memcpy (&m_ptBuffer[ m_uiTmpIndex ], ptItem, sizeof(T) * iNumOfItems); + return; + } + else + { + ZASSERT (m_uiSize - m_uiTmpIndex <= 0); + ZASSERT (iNumOfItems - m_uiSize + m_uiTmpIndex <= 0); + memcpy (&m_ptBuffer[ m_uiTmpIndex ], ptItem, sizeof(T) * (m_uiSize - m_uiTmpIndex)); + memcpy (m_ptBuffer, &ptItem[m_uiSize - m_uiTmpIndex], sizeof(T) * (iNumOfItems - m_uiSize + m_uiTmpIndex)); + return; + } +} + + +//******************************************************************** +// @method: GetPreInc +// @parameter: +// @result: T +// @author: Tim Flohrer +// @notes: increments the read pointer and +// gets an item at the current read pointer +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE T GetPreInc() + { + m_uiReadIndex = (m_uiReadIndex + 1) & m_uiMask; + return m_ptBuffer[ m_uiReadIndex ]; + } + + +//******************************************************************** +// @method: PutPreInc +// @parameter: T tItem +// @result: +// @author: Tim Flohrer +// @notes: increments the write pointer and +// puts an item at the current write pointer +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE void PutPreInc(T tItem) + { + m_uiWriteIndex = (m_uiWriteIndex + 1) & m_uiMask; + m_ptBuffer[ m_uiWriteIndex ] = tItem; + } + + +//******************************************************************** +// @method: GetPostDec +// @parameter: +// @result: T +// @author: Tim Flohrer +// @notes: gets an item at the current read pointer +// and Decrements the read pointer afterwards +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE T GetPostDec() + { + m_uiTmpIndex = m_uiReadIndex; + m_uiReadIndex = (m_uiReadIndex - 1 + m_uiSize) & m_uiMask; + return m_ptBuffer[ m_uiTmpIndex ]; + } + +//******************************************************************** +// @method: PutPostDec +// @parameter: T tItem +// @result: +// @author: Tim Flohrer +// @notes: puts an item at the current read pointer +// and Decrements the write pointer afterwards +// @creation date: 18.7.2001 +// @last modified: +//******************************************************************** +INLINE void PutPostDec(T tItem) + { + m_uiTmpIndex = m_uiWriteIndex; + m_uiWriteIndex = (m_uiWriteIndex - 1 + m_uiSize) & m_uiMask; + m_ptBuffer[ m_uiTmpIndex ] = tItem; + } + + +//******************************************************************** +// @method: ... [truncated message content] |