ref: 0c961661e920b7cd4750d4746e0039c7048dd904
parent: 351af0b48056c3b631cdd9c5225a17b720502274
author: idigdoug <idigdoug>
date: Wed Jan 6 08:03:56 EST 2010
Add SpeexDSP effect to sox for easy-to-use automatic gain control and noise reduction filter.
--- a/msvc9/LibSoX.vcproj
+++ b/msvc9/LibSoX.vcproj
@@ -41,7 +41,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="SoX;../../ffmpeg;../../flac/include;../../lame/include;../../lame;../../libid3tag;../../libmad;../../libpng;../../libogg/include;sndfile;../../libvorbis/include;../../wavpack/include;../../wavpack;../../zlib"
+ AdditionalIncludeDirectories="SoX;../../ffmpeg;../../flac/include;../../lame/include;../../lame;../../libid3tag;../../libmad;../../libpng;../../libogg/include;sndfile;../../speex/include;../../libvorbis/include;../../wavpack/include;../../wavpack;../../zlib"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
MinimalRebuild="true"
@@ -114,7 +114,7 @@
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="SoX;../../ffmpeg;../../flac/include;../../lame/include;../../lame;../../libid3tag;../../libmad;../../libpng;../../libogg/include;sndfile;../../libvorbis/include;../../wavpack/include;../../wavpack;../../zlib"
+ AdditionalIncludeDirectories="SoX;../../ffmpeg;../../flac/include;../../lame/include;../../lame;../../libid3tag;../../libmad;../../libpng;../../libogg/include;sndfile;../../speex/include;../../libvorbis/include;../../wavpack/include;../../wavpack;../../zlib"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
ExceptionHandling="0"
@@ -805,6 +805,10 @@
</File>
<File
RelativePath="..\src\speed.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\speexdsp.c"
>
</File>
<File
--- /dev/null
+++ b/msvc9/LibSpeex.vcproj
@@ -1,0 +1,452 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="LibSpeex"
+ ProjectGUID="{60902B83-8B26-4DBD-B635-4CECF5F4744C}"
+ RootNamespace="LibSpeex"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)\lib\"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../speex/include;../../speex/win32"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;M_PI=3.14159265358979323846"
+ StringPooling="true"
+ MinimalRebuild="true"
+ ExceptionHandling="0"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4018;4244"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)\lib\"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="../../speex/include;../../speex/win32"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;M_PI=3.14159265358979323846"
+ StringPooling="true"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ FloatingPointModel="2"
+ RuntimeTypeInfo="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4018;4244"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\speex\libspeex\bits.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\cb_search.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\exc_10_16_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\exc_10_32_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\exc_20_32_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\exc_5_256_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\exc_5_64_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\exc_8_128_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\fftwrap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\filterbank.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\filters.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\gain_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\gain_table_lbr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\hexc_10_32_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\hexc_table.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\high_lsp_tables.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\jitter.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\kiss_fft.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\kiss_fftr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\lpc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\lsp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\lsp_tables_nb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\ltp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\mdf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\modes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\modes_wb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\nb_celp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\preprocess.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\quant_lsp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\sb_celp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\scal.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\smallft.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\speex.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\speex_callbacks.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\speex_header.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\stereo.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\vbr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\vq.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\window.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\speex\libspeex\cb_search.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\cb_search_sse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\win32\config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\fftwrap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\filterbank.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\filters.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\filters_sse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\fixed_bfin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\fixed_debug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\fixed_generic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\kiss_fft.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\kiss_fftr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\lpc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\lsp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\ltp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\ltp_sse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\math_approx.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\modes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\nb_celp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\os_support.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\pseudofloat.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\quant_lsp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\resample_sse.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\sb_celp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\smallft.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\stack_alloc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\vbr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\vorbis_psy.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\vq.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\speex\libspeex\vq_sse.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--- a/msvc9/Sox.sln
+++ b/msvc9/Sox.sln
@@ -10,6 +10,7 @@
{F17BE535-C7E8-4930-A6FD-32498D73A533} = {F17BE535-C7E8-4930-A6FD-32498D73A533}
{7461CC57-B1CB-4766-B357-F51587449474} = {7461CC57-B1CB-4766-B357-F51587449474}
{BEE9F57C-384E-4C99-87EB-629BF45C8A89} = {BEE9F57C-384E-4C99-87EB-629BF45C8A89}
+ {60902B83-8B26-4DBD-B635-4CECF5F4744C} = {60902B83-8B26-4DBD-B635-4CECF5F4744C}
{342BDA83-C83F-4168-8425-E1DF72F47018} = {342BDA83-C83F-4168-8425-E1DF72F47018}
{46E7AC9D-3E96-4B34-B493-501BC277D6F9} = {46E7AC9D-3E96-4B34-B493-501BC277D6F9}
{C5C229AC-316D-42CB-9CA3-329619618972} = {C5C229AC-316D-42CB-9CA3-329619618972}
@@ -55,6 +56,8 @@
{D2572DE1-610E-46A4-8DD2-8A693347D76A} = {D2572DE1-610E-46A4-8DD2-8A693347D76A}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibSpeex", "LibSpeex.vcproj", "{60902B83-8B26-4DBD-B635-4CECF5F4744C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -125,6 +128,10 @@
{342BDA83-C83F-4168-8425-E1DF72F47018}.Debug|Win32.Build.0 = Debug|Win32
{342BDA83-C83F-4168-8425-E1DF72F47018}.Release|Win32.ActiveCfg = Release|Win32
{342BDA83-C83F-4168-8425-E1DF72F47018}.Release|Win32.Build.0 = Release|Win32
+ {60902B83-8B26-4DBD-B635-4CECF5F4744C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {60902B83-8B26-4DBD-B635-4CECF5F4744C}.Debug|Win32.Build.0 = Debug|Win32
+ {60902B83-8B26-4DBD-B635-4CECF5F4744C}.Release|Win32.ActiveCfg = Release|Win32
+ {60902B83-8B26-4DBD-B635-4CECF5F4744C}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
--- a/src/effects.h
+++ b/src/effects.h
@@ -78,6 +78,9 @@
EFFECT(spectrogram)
#endif
EFFECT(speed)
+#ifdef HAVE_SPEEXDSP
+ EFFECT(speexdsp)
+#endif
EFFECT(splice)
EFFECT(stat)
EFFECT(stats)
--- /dev/null
+++ b/src/speexdsp.c
@@ -1,0 +1,346 @@
+/* libSoX effect: SpeexDsp effect to apply processing from libspeexdsp.
+ *
+ * Copyright 1999-2009 Chris Bagwell And SoX Contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "sox_i.h"
+
+#ifdef HAVE_SPEEXDSP
+
+#include <speex/speex_types.h>
+#include <speex/speex_preprocess.h>
+
+/* Private data for effect */
+typedef struct speexdsp_priv_t {
+ size_t buffer_end; /* Index of the end of the buffer. */
+ size_t buffer_ipos; /* Index for the next input sample. */
+ size_t buffer_opos; /* Index of the next sample that has not been drained. */
+ int16_t* buffer; /* Work buffer. */
+ SpeexPreprocessState* sps;/* DSP state. */
+ size_t agc; /* Param: Automatic Gain Control target volume level: 0 to disable, or 1-100 (target volume). */
+ size_t denoise; /* Param: Denoise: 0 to disable, or maximum noise attenuation in dB. */
+ size_t dereverb; /* Param: Dereverb: 0 to disable, 1 to enable. */
+ size_t frames_per_second; /* Param: Used to compute buffer size from sample rate. */
+ size_t samples_per_frame; /* Param: Used to compute buffer size directly. Default is to use frames_per_second instead. */
+} priv_t;
+
+static int get_param(
+ int* pArgc,
+ char*** pArgv,
+ size_t* pParam,
+ size_t default_val,
+ size_t min_valid,
+ size_t max_valid)
+{
+ *pParam = default_val;
+ if (*pArgc > 1 && (*pArgv)[1][0] != '-')
+ {
+ char* arg_end;
+ *pParam = strtoul((*pArgv)[1], &arg_end, 0);
+ if (!arg_end || arg_end[0] || *pParam < min_valid || max_valid <= *pParam)
+ return 0;
+
+ --*pArgc;
+ ++*pArgv;
+ }
+
+ return 1;
+}
+
+/*
+ * Process command-line options but don't do other
+ * initialization now: effp->in_signal & effp->out_signal are not
+ * yet filled in.
+ */
+static int getopts(sox_effect_t* effp, int argc, char** argv)
+{
+ priv_t* p = (priv_t*)effp->priv;
+ const size_t agcDefault = 100;
+ const size_t denoiseDefault = 15;
+ const size_t fpsDefault = 50;
+
+ for (argc--, argv++; argc; argc--, argv++)
+ {
+ if (!strcasecmp("-agc", argv[0]))
+ {
+ /* AGC level argument is optional. If not specified, it defaults to agcDefault.
+ If specified, it must be from 0 to 100. */
+ if (!get_param(&argc, &argv, &p->agc, agcDefault, 0, 100))
+ {
+ lsx_fail("Invalid argument \"%s\" to -agc parameter - expected number from 0 to 100.", argv[1]);
+ return lsx_usage(effp);
+ }
+ }
+ else if (!strcasecmp("-denoise", argv[0]))
+ {
+ /* Denoise level argument is optional. If not specified, it defaults to denoiseDefault.
+ If specified, it must be from 0 to 100. */
+ if (!get_param(&argc, &argv, &p->denoise, denoiseDefault, 0, 100))
+ {
+ lsx_fail("Invalid argument \"%s\" to -denoise parameter - expected number from 0 to 100.", argv[1]);
+ return lsx_usage(effp);
+ }
+ }
+ else if (!strcasecmp("-dereverb", argv[0]))
+ {
+ p->dereverb = 1;
+ }
+ else if (!strcasecmp("-spf", argv[0]))
+ {
+ /* If samples_per_frame option is given, argument is required and must be
+ greater than 0. */
+ if (!get_param(&argc, &argv, &p->samples_per_frame, 0, 1, 1000000000) || !p->samples_per_frame)
+ {
+ lsx_fail("Invalid argument \"%s\" to -spf parameter - expected positive number.", argv[1]);
+ return lsx_usage(effp);
+ }
+ }
+ else if (!strcasecmp("-fps", argv[0]))
+ {
+ /* If frames_per_second option is given, argument is required and must be
+ from 1 to 100. This will be used later to compute samples_per_frame once
+ we know the sample rate). */
+ if (!get_param(&argc, &argv, &p->frames_per_second, 0, 1, 100) || !p->frames_per_second)
+ {
+ lsx_fail("Invalid argument \"%s\" to -fps parameter - expected number from 1 to 100.", argv[1]);
+ return lsx_usage(effp);
+ }
+ }
+ else
+ {
+ lsx_fail("Invalid parameter \"%s\".", argv[0]);
+ return lsx_usage(effp);
+ }
+ }
+
+ if (!p->frames_per_second)
+ p->frames_per_second = fpsDefault;
+
+ if (!p->agc && !p->denoise && !p->dereverb)
+ {
+ lsx_report("No features specified. Enabling default settings \"-agc %u -denoise %u\".", agcDefault, denoiseDefault);
+ p->agc = agcDefault;
+ p->denoise = denoiseDefault;
+ }
+
+ return SOX_SUCCESS;
+}
+
+/*
+ * Do anything required when you stop reading samples.
+ */
+static int stop(sox_effect_t* effp)
+{
+ priv_t* p = (priv_t*)effp->priv;
+
+ if (p->sps)
+ {
+ speex_preprocess_state_destroy(p->sps);
+ p->sps = NULL;
+ }
+
+ if (p->buffer)
+ {
+ free(p->buffer);
+ p->buffer = NULL;
+ }
+
+ return SOX_SUCCESS;
+}
+
+/*
+ * Prepare processing.
+ * Do all initializations.
+ */
+static int start(sox_effect_t* effp)
+{
+ priv_t* p = (priv_t*)effp->priv;
+ int result = SOX_SUCCESS;
+ spx_int32_t int_val;
+ float float_val;
+
+ if (p->samples_per_frame)
+ {
+ p->buffer_end = p->samples_per_frame;
+ }
+ else
+ {
+ p->buffer_end = effp->in_signal.rate / p->frames_per_second;
+ if (!p->buffer_end)
+ {
+ lsx_fail("frames_per_second too large for the current sample rate.");
+ return SOX_EOF;
+ }
+ }
+
+ p->buffer_opos = p->buffer_end;
+ effp->out_signal.precision = 16;
+
+ p->buffer = lsx_malloc(p->buffer_end * sizeof(p->buffer[0]));
+ if (!p->buffer)
+ {
+ result = SOX_ENOMEM;
+ goto Done;
+ }
+
+ p->sps = speex_preprocess_state_init(p->buffer_end, effp->in_signal.rate);
+ if (!p->sps)
+ {
+ lsx_fail("Failed to initialize preprocessor DSP.");
+ result = SOX_EOF;
+ goto Done;
+ }
+
+ int_val = p->agc ? 1 : 2;
+ speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_AGC, &int_val);
+ if (p->agc)
+ {
+ float_val = p->agc * 327.68f;
+ speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_AGC_LEVEL, &float_val);
+ }
+
+ int_val = p->denoise ? 1 : 2;
+ speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_DENOISE, &int_val);
+ if (p->denoise)
+ {
+ int_val = -(spx_int32_t)p->denoise;
+ speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &int_val);
+ }
+
+ int_val = p->dereverb ? 1 : 2;
+ speex_preprocess_ctl(p->sps, SPEEX_PREPROCESS_SET_DEREVERB, &int_val);
+
+Done:
+ if (result != SOX_SUCCESS)
+ stop(effp);
+
+ return result;
+}
+
+/*
+ * Process up to *isamp samples from ibuf and produce up to *osamp samples
+ * in obuf. Write back the actual numbers of samples to *isamp and *osamp.
+ * Return SOX_SUCCESS or, if error occurs, SOX_EOF.
+ */
+static int flow(
+ sox_effect_t* effp,
+ const sox_sample_t* ibuf,
+ sox_sample_t* obuf,
+ size_t* isamp,
+ size_t* osamp)
+{
+ priv_t* p = (priv_t*)effp->priv;
+ size_t ibuf_pos = 0;
+ size_t ibuf_end = *isamp;
+ size_t obuf_pos = 0;
+ size_t obuf_end = *osamp;
+ size_t end_pos;
+ SOX_SAMPLE_LOCALS;
+
+ for (;;)
+ {
+ /* Write any processed data in working buffer to the output buffer. */
+ end_pos = obuf_pos + min(p->buffer_end - p->buffer_opos, obuf_end - obuf_pos);
+ for (; obuf_pos < end_pos; obuf_pos++, p->buffer_opos++)
+ obuf[obuf_pos] = SOX_SIGNED_16BIT_TO_SAMPLE(p->buffer[p->buffer_opos], dummy);
+ if (p->buffer_opos != p->buffer_end)
+ break; /* Output buffer is full and we still have more processed data. */
+
+ /* Fill working buffer from input buffer. */
+ end_pos = ibuf_pos + min(p->buffer_end - p->buffer_ipos, ibuf_end - ibuf_pos);
+ for (; ibuf_pos < end_pos; ibuf_pos++, p->buffer_ipos++)
+ p->buffer[p->buffer_ipos] = SOX_SAMPLE_TO_SIGNED_16BIT(ibuf[ibuf_pos], effp->clips);
+ if (p->buffer_ipos != p->buffer_end)
+ break; /* Working buffer is not full and there is no more input data. */
+
+ speex_preprocess_run(p->sps, p->buffer);
+ p->buffer_ipos = 0;
+ p->buffer_opos = 0;
+ }
+
+ *isamp = ibuf_pos;
+ *osamp = obuf_pos;
+ return SOX_SUCCESS;
+}
+
+/*
+ * Drain out remaining samples if the effect generates any.
+ */
+static int drain(sox_effect_t* effp, sox_sample_t* obuf, size_t* osamp)
+{
+ priv_t* p = (priv_t*)effp->priv;
+ size_t obuf_pos = 0;
+ size_t obuf_end = *osamp;
+ size_t i;
+ size_t end_pos;
+
+ /* Input that hasn't been processed yet? */
+ if (p->buffer_ipos != 0)
+ {
+ /* DSP only works on full frames, so fill the remaining space with 0s. */
+ for (i = p->buffer_ipos; i < p->buffer_end; i++)
+ p->buffer[i] = 0;
+ speex_preprocess_run(p->sps, p->buffer);
+ p->buffer_end = p->buffer_ipos;
+ p->buffer_ipos = 0;
+ p->buffer_opos = 0;
+ }
+
+ end_pos = obuf_pos + min(p->buffer_end - p->buffer_opos, obuf_end - obuf_pos);
+ for (; obuf_pos < end_pos; obuf_pos++, p->buffer_opos++)
+ obuf[obuf_pos] = SOX_SIGNED_16BIT_TO_SAMPLE(p->buffer[p->buffer_opos], dummy);
+
+ *osamp = obuf_pos;
+ return
+ p->buffer_opos != p->buffer_end
+ ? SOX_SUCCESS
+ : SOX_EOF;
+}
+
+/*
+ * Function returning effect descriptor. This should be the only
+ * externally visible object.
+ */
+const sox_effect_handler_t* lsx_speexdsp_effect_fn(void)
+{
+ /*
+ * Effect descriptor.
+ * If no specific processing is needed for any of
+ * the 6 functions, then the function above can be deleted
+ * and NULL used in place of the its name below.
+ */
+ static sox_effect_handler_t sox_speexdsp_effect = {
+ "speexdsp",
+ "Uses the Speex DSP library to improve perceived sound quality.\n"
+ "If no options are specified, the -agc and -denoise features are enabled.\n"
+ "Options:\n"
+ "-agc [target_level] Enable automatic gain control, and optionally specify a\n"
+ " target volume level from 1-100 (default is 100).\n"
+ "-denoise [max_dB] Enable noise reduction, and optionally specify the max\n"
+ " attenuation (default is 15).\n"
+ "-dereverb Enable reverb reduction.\n"
+ "-fps frames_per_second Specify the number of frames per second from 1-100\n"
+ " (default is 20).\n"
+ "-spf samples_per_frame Specify the number of samples per frame. Default is to\n"
+ " use the -fps setting.",
+ SOX_EFF_PREC | SOX_EFF_GAIN,
+ getopts, start, flow, drain, stop, NULL, sizeof(priv_t)
+ };
+ return &sox_speexdsp_effect;
+}
+
+#endif /* HAVE_SPEEXDSP */