1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-29 14:48:39 +02:00

No naked malloc (calloc, strup, ...) and free!

This commit is contained in:
Paul Licameli 2017-03-09 09:54:43 -05:00
commit a399d4e23a
47 changed files with 727 additions and 923 deletions

View File

@ -521,7 +521,7 @@ class GnomeShutdown
public: public:
GnomeShutdown() GnomeShutdown()
{ {
mArgv[0] = strdup("Audacity"); mArgv[0].reset(strdup("Audacity"));
mGnomeui = dlopen("libgnomeui-2.so.0", RTLD_NOW); mGnomeui = dlopen("libgnomeui-2.so.0", RTLD_NOW);
if (!mGnomeui) { if (!mGnomeui) {
@ -550,11 +550,11 @@ class GnomeShutdown
return; return;
} }
gnome_program_init(mArgv[0], gnome_program_init(mArgv[0].get(),
"1.0", "1.0",
libgnomeui_module_info_get(), libgnomeui_module_info_get(),
1, 1,
mArgv, reinterpret_cast<char**>(mArgv),
NULL); NULL);
mClient = gnome_master_client(); mClient = gnome_master_client();
@ -568,13 +568,11 @@ class GnomeShutdown
virtual ~GnomeShutdown() virtual ~GnomeShutdown()
{ {
// Do not dlclose() the libraries here lest you want segfaults... // Do not dlclose() the libraries here lest you want segfaults...
free(mArgv[0]);
} }
private: private:
char *mArgv[1]; MallocString<> mArgv[1];
void *mGnomeui; void *mGnomeui;
void *mGnome; void *mGnome;
GnomeClient *mClient; GnomeClient *mClient;

View File

@ -113,8 +113,6 @@ void InitFFT()
void DeinitFFT() void DeinitFFT()
{ {
gFFTBitTable.reset(); gFFTBitTable.reset();
// Deallocate any unused RealFFTf tables
CleanupFFT();
} }
static inline size_t FastReverseBits(size_t i, size_t NumBits) static inline size_t FastReverseBits(size_t i, size_t NumBits)
@ -230,14 +228,14 @@ void FFT(size_t NumSamples,
void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *ImagOut) void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *ImagOut)
{ {
HFFT hFFT = GetFFT(NumSamples); auto hFFT = GetFFT(NumSamples);
Floats pFFT{ NumSamples }; Floats pFFT{ NumSamples };
// Copy the data into the processing buffer // Copy the data into the processing buffer
for(size_t i = 0; i < NumSamples; i++) for(size_t i = 0; i < NumSamples; i++)
pFFT[i] = RealIn[i]; pFFT[i] = RealIn[i];
// Perform the FFT // Perform the FFT
RealFFTf(pFFT.get(), hFFT); RealFFTf(pFFT.get(), hFFT.get());
// Copy the data into the real and imaginary outputs // Copy the data into the real and imaginary outputs
for (size_t i = 1; i<(NumSamples / 2); i++) { for (size_t i = 1; i<(NumSamples / 2); i++) {
@ -253,8 +251,6 @@ void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *Imag
RealOut[i] = RealOut[NumSamples-i]; RealOut[i] = RealOut[NumSamples-i];
ImagOut[i] = -ImagOut[NumSamples-i]; ImagOut[i] = -ImagOut[NumSamples-i];
} }
ReleaseFFT(hFFT);
} }
/* /*
@ -271,7 +267,7 @@ void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *Imag
void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn, void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn,
float *RealOut) float *RealOut)
{ {
HFFT hFFT = GetFFT(NumSamples); auto hFFT = GetFFT(NumSamples);
Floats pFFT{ NumSamples }; Floats pFFT{ NumSamples };
// Copy the data into the processing buffer // Copy the data into the processing buffer
for (size_t i = 0; i < (NumSamples / 2); i++) for (size_t i = 0; i < (NumSamples / 2); i++)
@ -287,12 +283,10 @@ void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn,
pFFT[1] = RealIn[NumSamples / 2]; pFFT[1] = RealIn[NumSamples / 2];
// Perform the FFT // Perform the FFT
InverseRealFFTf(pFFT.get(), hFFT); InverseRealFFTf(pFFT.get(), hFFT.get());
// Copy the data to the (purely real) output buffer // Copy the data to the (purely real) output buffer
ReorderToTime(hFFT, pFFT.get(), RealOut); ReorderToTime(hFFT.get(), pFFT.get(), RealOut);
ReleaseFFT(hFFT);
} }
/* /*
@ -308,14 +302,14 @@ void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn,
void PowerSpectrum(size_t NumSamples, const float *In, float *Out) void PowerSpectrum(size_t NumSamples, const float *In, float *Out)
{ {
HFFT hFFT = GetFFT(NumSamples); auto hFFT = GetFFT(NumSamples);
Floats pFFT{ NumSamples }; Floats pFFT{ NumSamples };
// Copy the data into the processing buffer // Copy the data into the processing buffer
for (size_t i = 0; i<NumSamples; i++) for (size_t i = 0; i<NumSamples; i++)
pFFT[i] = In[i]; pFFT[i] = In[i];
// Perform the FFT // Perform the FFT
RealFFTf(pFFT.get(), hFFT); RealFFTf(pFFT.get(), hFFT.get());
// Copy the data into the real and imaginary outputs // Copy the data into the real and imaginary outputs
for (size_t i = 1; i<NumSamples / 2; i++) { for (size_t i = 1; i<NumSamples / 2; i++) {
@ -325,7 +319,6 @@ void PowerSpectrum(size_t NumSamples, const float *In, float *Out)
// Handle the (real-only) DC and Fs/2 bins // Handle the (real-only) DC and Fs/2 bins
Out[0] = pFFT[0]*pFFT[0]; Out[0] = pFFT[0]*pFFT[0];
Out[NumSamples / 2] = pFFT[1]*pFFT[1]; Out[NumSamples / 2] = pFFT[1]*pFFT[1];
ReleaseFFT(hFFT);
} }
/* /*

View File

@ -386,10 +386,10 @@ int import_ffmpeg_decode_frame(streamContext *sc, bool flushing)
} }
sc->m_samplefmt = sc->m_codecCtx->sample_fmt; sc->m_samplefmt = sc->m_codecCtx->sample_fmt;
sc->m_samplesize = av_get_bytes_per_sample(sc->m_samplefmt); sc->m_samplesize = static_cast<size_t>(av_get_bytes_per_sample(sc->m_samplefmt));
int channels = sc->m_codecCtx->channels; int channels = sc->m_codecCtx->channels;
unsigned int newsize = sc->m_samplesize * frame->nb_samples * channels; auto newsize = sc->m_samplesize * frame->nb_samples * channels;
sc->m_decodedAudioSamplesValidSiz = newsize; sc->m_decodedAudioSamplesValidSiz = newsize;
// Reallocate the audio sample buffer if it's smaller than the frame size. // Reallocate the audio sample buffer if it's smaller than the frame size.
if (newsize > sc->m_decodedAudioSamplesSiz ) if (newsize > sc->m_decodedAudioSamplesSiz )

View File

@ -982,13 +982,13 @@ struct streamContext
int m_frameValid{}; // is m_decodedVideoFrame/m_decodedAudioSamples valid? int m_frameValid{}; // is m_decodedVideoFrame/m_decodedAudioSamples valid?
AVMallocHolder<uint8_t> m_decodedAudioSamples; // decoded audio samples stored here AVMallocHolder<uint8_t> m_decodedAudioSamples; // decoded audio samples stored here
unsigned int m_decodedAudioSamplesSiz{}; // current size of m_decodedAudioSamples unsigned int m_decodedAudioSamplesSiz{}; // current size of m_decodedAudioSamples
int m_decodedAudioSamplesValidSiz{}; // # valid bytes in m_decodedAudioSamples size_t m_decodedAudioSamplesValidSiz{}; // # valid bytes in m_decodedAudioSamples
int m_initialchannels{}; // number of channels allocated when we begin the importing. Assumes that number of channels doesn't change on the fly. int m_initialchannels{}; // number of channels allocated when we begin the importing. Assumes that number of channels doesn't change on the fly.
int m_samplesize{}; // input sample size in bytes size_t m_samplesize{}; // input sample size in bytes
AVSampleFormat m_samplefmt{ AV_SAMPLE_FMT_NONE }; // input sample format AVSampleFormat m_samplefmt{ AV_SAMPLE_FMT_NONE }; // input sample format
int m_osamplesize{}; // output sample size in bytes size_t m_osamplesize{}; // output sample size in bytes
sampleFormat m_osamplefmt{ floatSample }; // output sample format sampleFormat m_osamplefmt{ floatSample }; // output sample format
streamContext() { memset(this, 0, sizeof(*this)); } streamContext() { memset(this, 0, sizeof(*this)); }

View File

@ -15,6 +15,8 @@ information.
*//*******************************************************************/ *//*******************************************************************/
#include "Audacity.h"
#include "MemoryX.h"
#include <wx/arrstr.h> #include <wx/arrstr.h>
#include <wx/intl.h> #include <wx/intl.h>
#include "sndfile.h" #include "sndfile.h"
@ -119,7 +121,6 @@ wxString sf_header_name(int format)
wxString sf_header_shortname(int format) wxString sf_header_shortname(int format)
{ {
SF_FORMAT_INFO format_info; SF_FORMAT_INFO format_info;
char *tmp;
int i; int i;
wxString s; wxString s;
@ -127,8 +128,7 @@ wxString sf_header_shortname(int format)
format_info.format = (format & SF_FORMAT_TYPEMASK); format_info.format = (format & SF_FORMAT_TYPEMASK);
sf_command(NULL, SFC_GET_FORMAT_INFO, &format_info, sizeof(format_info)); sf_command(NULL, SFC_GET_FORMAT_INFO, &format_info, sizeof(format_info));
tmp = (char *)malloc(strlen(format_info.name)+1); MallocString<> tmp { strdup( format_info.name ) };
strcpy(tmp, format_info.name);
i = 0; i = 0;
while(tmp[i]) { while(tmp[i]) {
if (tmp[i]==' ') if (tmp[i]==' ')
@ -137,9 +137,7 @@ wxString sf_header_shortname(int format)
i++; i++;
} }
s = LAT1CTOWX(tmp); s = LAT1CTOWX(tmp.get());
free(tmp);
return s; return s;
} }

View File

@ -37,11 +37,14 @@
*/ */
#include "Audacity.h" #include "Audacity.h"
#include <vector>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
#include "Experimental.h" #include "Experimental.h"
#include <wx/thread.h>
#include "RealFFTf.h" #include "RealFFTf.h"
#ifdef EXPERIMENTAL_EQ_SSE_THREADED #ifdef EXPERIMENTAL_EQ_SSE_THREADED
#include "RealFFTf48x.h" #include "RealFFTf48x.h"
@ -58,13 +61,8 @@
HFFT InitializeFFT(size_t fftlen) HFFT InitializeFFT(size_t fftlen)
{ {
int temp; int temp;
HFFT h; HFFT h{ safenew FFTParam };
if((h=(HFFT)malloc(sizeof(FFTParam)))==NULL)
{
fprintf(stderr,"Error allocating memory for FFT\n");
exit(8);
}
/* /*
* FFT size is only half the number of data points * FFT size is only half the number of data points
* The full FFT output can be reconstructed from this FFT's output. * The full FFT output can be reconstructed from this FFT's output.
@ -72,17 +70,9 @@ HFFT InitializeFFT(size_t fftlen)
*/ */
h->Points = fftlen / 2; h->Points = fftlen / 2;
if((h->SinTable=(fft_type *)malloc(2*h->Points*sizeof(fft_type)))==NULL) h->SinTable.reinit(2*h->Points);
{
fprintf(stderr,"Error allocating memory for Sine table.\n");
exit(8);
}
if((h->BitReversed=(int *)malloc(h->Points*sizeof(int)))==NULL) h->BitReversed.reinit(h->Points);
{
fprintf(stderr,"Error allocating memory for BitReversed.\n");
exit(8);
}
for(size_t i = 0; i < h->Points; i++) for(size_t i = 0; i < h->Points; i++)
{ {
@ -109,40 +99,33 @@ HFFT InitializeFFT(size_t fftlen)
return h; return h;
} }
/*
* Free up the memory allotted for Sin table and Twiddle Pointers
*/
void EndFFT(HFFT h)
{
if(h->Points > 0) {
free(h->BitReversed);
free(h->SinTable);
}
h->Points = 0;
free(h);
}
enum : size_t { MAX_HFFT = 10 }; enum : size_t { MAX_HFFT = 10 };
static HFFT hFFTArray[MAX_HFFT] = { NULL };
static int nFFTLockCount[MAX_HFFT] = { 0 }; // Maintain a pool:
static std::vector< movable_ptr<FFTParam> > hFFTArray(MAX_HFFT);
wxCriticalSection getFFTMutex;
/* Get a handle to the FFT tables of the desired length */ /* Get a handle to the FFT tables of the desired length */
/* This version keeps common tables rather than allocating a NEW table every time */ /* This version keeps common tables rather than allocating a NEW table every time */
HFFT GetFFT(size_t fftlen) HFFT GetFFT(size_t fftlen)
{ {
// To do: smarter policy about when to retain in the pool and when to
// allocate a unique instance.
wxCriticalSectionLocker locker{ getFFTMutex };
size_t h = 0; size_t h = 0;
auto n = fftlen/2; auto n = fftlen/2;
auto size = hFFTArray.size();
for(; for(;
(h < MAX_HFFT) && (hFFTArray[h] != NULL) && (n != hFFTArray[h]->Points); (h < size) && hFFTArray[h] && (n != hFFTArray[h]->Points);
h++) h++)
; ;
if(h < MAX_HFFT) { if(h < size) {
if(hFFTArray[h] == NULL) { if(hFFTArray[h] == NULL) {
hFFTArray[h] = InitializeFFT(fftlen); hFFTArray[h].reset( InitializeFFT(fftlen).release() );
nFFTLockCount[h] = 0;
} }
nFFTLockCount[h]++; return HFFT{ hFFTArray[h].get() };
return hFFTArray[h];
} else { } else {
// All buffers used, so fall back to allocating a NEW set of tables // All buffers used, so fall back to allocating a NEW set of tables
return InitializeFFT(fftlen); return InitializeFFT(fftlen);
@ -150,31 +133,21 @@ HFFT GetFFT(size_t fftlen)
} }
/* Release a previously requested handle to the FFT tables */ /* Release a previously requested handle to the FFT tables */
void ReleaseFFT(HFFT hFFT) void FFTDeleter::operator() (FFTParam *hFFT) const
{ {
int h; wxCriticalSectionLocker locker{ getFFTMutex };
for(h=0; (h<MAX_HFFT) && (hFFTArray[h] != hFFT); h++);
if(h<MAX_HFFT) {
nFFTLockCount[h]--;
} else {
EndFFT(hFFT);
}
}
/* Deallocate any unused FFT tables */ auto it = hFFTArray.begin(), end = hFFTArray.end();
void CleanupFFT() while (it != end && it->get() != hFFT)
{ ++it;
int h; if ( it != end )
for(h=0; (h<MAX_HFFT); h++) { ;
if((nFFTLockCount[h] <= 0) && (hFFTArray[h] != NULL)) { else
EndFFT(hFFTArray[h]); delete hFFT;
hFFTArray[h] = NULL;
}
}
} }
/* /*
* Forward FFT routine. Must call InitializeFFT(fftlen) first! * Forward FFT routine. Must call GetFFT(fftlen) first!
* *
* Note: Output is BIT-REVERSED! so you must use the BitReversed to * Note: Output is BIT-REVERSED! so you must use the BitReversed to
* get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ] * get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ]
@ -191,7 +164,7 @@ void CleanupFFT()
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void RealFFTf(fft_type *buffer,HFFT h) void RealFFTf(fft_type *buffer, const FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
const fft_type *sptr; const fft_type *sptr;
@ -216,7 +189,7 @@ void RealFFTf(fft_type *buffer,HFFT h)
{ {
A = buffer; A = buffer;
B = buffer + ButterfliesPerGroup * 2; B = buffer + ButterfliesPerGroup * 2;
sptr = h->SinTable; sptr = h->SinTable.get();
while(A < endptr1) while(A < endptr1)
{ {
@ -239,8 +212,8 @@ void RealFFTf(fft_type *buffer,HFFT h)
ButterfliesPerGroup >>= 1; ButterfliesPerGroup >>= 1;
} }
/* Massage output to get the output for a real input sequence. */ /* Massage output to get the output for a real input sequence. */
br1 = h->BitReversed + 1; br1 = h->BitReversed.get() + 1;
br2 = h->BitReversed + h->Points - 1; br2 = h->BitReversed.get() + h->Points - 1;
while(br1<br2) while(br1<br2)
{ {
@ -281,7 +254,7 @@ void RealFFTf(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -293,7 +266,7 @@ void RealFFTf(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf(fft_type *buffer,HFFT h) void InverseRealFFTf(fft_type *buffer, const FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
const fft_type *sptr; const fft_type *sptr;
@ -307,7 +280,7 @@ void InverseRealFFTf(fft_type *buffer,HFFT h)
/* Massage input to get the input for a real output sequence. */ /* Massage input to get the input for a real output sequence. */
A = buffer + 2; A = buffer + 2;
B = buffer + h->Points * 2 - 2; B = buffer + h->Points * 2 - 2;
br1 = h->BitReversed + 1; br1 = h->BitReversed.get() + 1;
while(A<B) while(A<B)
{ {
sin=h->SinTable[*br1]; sin=h->SinTable[*br1];
@ -353,7 +326,7 @@ void InverseRealFFTf(fft_type *buffer,HFFT h)
{ {
A = buffer; A = buffer;
B = buffer + ButterfliesPerGroup * 2; B = buffer + ButterfliesPerGroup * 2;
sptr = h->SinTable; sptr = h->SinTable.get();
while(A < endptr1) while(A < endptr1)
{ {
@ -376,7 +349,7 @@ void InverseRealFFTf(fft_type *buffer,HFFT h)
} }
} }
void ReorderToFreq(HFFT hFFT, const fft_type *buffer, void ReorderToFreq(const FFTParam *hFFT, const fft_type *buffer,
fft_type *RealOut, fft_type *ImagOut) fft_type *RealOut, fft_type *ImagOut)
{ {
// Copy the data into the real and imaginary outputs // Copy the data into the real and imaginary outputs
@ -390,7 +363,7 @@ void ReorderToFreq(HFFT hFFT, const fft_type *buffer,
ImagOut[hFFT->Points] = 0; ImagOut[hFFT->Points] = 0;
} }
void ReorderToTime(HFFT hFFT, const fft_type *buffer, fft_type *TimeOut) void ReorderToTime(const FFTParam *hFFT, const fft_type *buffer, fft_type *TimeOut)
{ {
// Copy the data into the real outputs // Copy the data into the real outputs
for(size_t i = 0; i < hFFT->Points; i++) { for(size_t i = 0; i < hFFT->Points; i++) {

View File

@ -1,28 +1,33 @@
#ifndef __realfftf_h #ifndef __realfftf_h
#define __realfftf_h #define __realfftf_h
#include "Audacity.h"
#include "Experimental.h" #include "Experimental.h"
#include "MemoryX.h"
#define fft_type float using fft_type = float;
struct FFTParam { struct FFTParam {
int *BitReversed; ArrayOf<int> BitReversed;
fft_type *SinTable; ArrayOf<fft_type> SinTable;
size_t Points; size_t Points;
#ifdef EXPERIMENTAL_EQ_SSE_THREADED #ifdef EXPERIMENTAL_EQ_SSE_THREADED
int pow2Bits; int pow2Bits;
#endif #endif
}; };
typedef FFTParam * HFFT;
HFFT InitializeFFT(size_t); struct FFTDeleter{
void EndFFT(HFFT); void operator () (FFTParam *p) const;
};
using HFFT = std::unique_ptr<
FFTParam, FFTDeleter
>;
HFFT GetFFT(size_t); HFFT GetFFT(size_t);
void ReleaseFFT(HFFT); void RealFFTf(fft_type *, const FFTParam *);
void CleanupFFT(); void InverseRealFFTf(fft_type *, const FFTParam *);
void RealFFTf(fft_type *,HFFT); void ReorderToTime(const FFTParam *hFFT, const fft_type *buffer, fft_type *TimeOut);
void InverseRealFFTf(fft_type *,HFFT); void ReorderToFreq(const FFTParam *hFFT, const fft_type *buffer,
void ReorderToTime(HFFT hFFT, const fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq(HFFT hFFT, const fft_type *buffer,
fft_type *RealOut, fft_type *ImagOut); fft_type *RealOut, fft_type *ImagOut);
#endif #endif

View File

@ -34,6 +34,8 @@
* and BitReversed tables so they don't need to be reallocated * and BitReversed tables so they don't need to be reallocated
* and recomputed on every call. * and recomputed on every call.
* - Added Reorder* functions to undo the bit-reversal * - Added Reorder* functions to undo the bit-reversal
* Modified 15 April 2016 Paul Licameli
* - C++11 smart pointers
* *
* Copyright (C) 2009 Philip VanBaren * Copyright (C) 2009 Philip VanBaren
* *
@ -146,7 +148,7 @@ int SmallRB(int bits, int numberBits)
}; };
/* wrapper funcitons. If passed -1 function choice will be made locally */ /* wrapper funcitons. If passed -1 function choice will be made locally */
void RealFFTf1x(fft_type *buffer, HFFT h, int functionType) void RealFFTf1x(fft_type *buffer, FFTParam *h, int functionType)
{ {
switch(functionType) { switch(functionType) {
case FFT_SinCosTableVBR16: case FFT_SinCosTableVBR16:
@ -167,7 +169,7 @@ void RealFFTf1x(fft_type *buffer, HFFT h, int functionType)
}; };
} }
void InverseRealFFTf1x(fft_type *buffer, HFFT h, int functionType) void InverseRealFFTf1x(fft_type *buffer, FFTParam *h, int functionType)
{ {
switch(functionType) { switch(functionType) {
case FFT_SinCosTableVBR16: case FFT_SinCosTableVBR16:
@ -188,7 +190,7 @@ void InverseRealFFTf1x(fft_type *buffer, HFFT h, int functionType)
}; };
} }
void ReorderToTime1x(HFFT hFFT, fft_type *buffer, fft_type *TimeOut, int functionType) void ReorderToTime1x(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut, int functionType)
{ {
switch(functionType) { switch(functionType) {
case FFT_SinCosTableVBR16: case FFT_SinCosTableVBR16:
@ -209,7 +211,7 @@ void ReorderToTime1x(HFFT hFFT, fft_type *buffer, fft_type *TimeOut, int functio
}; };
} }
void ReorderToFreq1x(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType) void ReorderToFreq1x(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType)
{ {
switch(functionType) { switch(functionType) {
case FFT_SinCosTableVBR16: case FFT_SinCosTableVBR16:
@ -230,7 +232,7 @@ void ReorderToFreq1x(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *I
}; };
} }
void RealFFTf4x( fft_type *buffer, HFFT h, int functionType) void RealFFTf4x( fft_type *buffer, FFTParam *h, int functionType)
{ {
switch(functionType) { switch(functionType) {
case FFT_SinCosTableVBR16: case FFT_SinCosTableVBR16:
@ -251,7 +253,7 @@ void RealFFTf4x( fft_type *buffer, HFFT h, int functionType)
}; };
} }
void InverseRealFFTf4x( fft_type *buffer, HFFT h, int functionType) void InverseRealFFTf4x( fft_type *buffer, FFTParam *h, int functionType)
{ {
switch(functionType) { switch(functionType) {
case FFT_SinCosTableVBR16: case FFT_SinCosTableVBR16:
@ -272,7 +274,7 @@ void InverseRealFFTf4x( fft_type *buffer, HFFT h, int functionType)
}; };
} }
void ReorderToTime4x(HFFT hFFT, fft_type *buffer, fft_type *TimeOut, int functionType) void ReorderToTime4x(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut, int functionType)
{ {
switch(functionType) { switch(functionType) {
case FFT_SinCosTableVBR16: case FFT_SinCosTableVBR16:
@ -293,7 +295,7 @@ void ReorderToTime4x(HFFT hFFT, fft_type *buffer, fft_type *TimeOut, int functio
}; };
} }
void ReorderToFreq4x(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType) void ReorderToFreq4x(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType)
{ {
switch(functionType) { switch(functionType) {
case FFT_SinCosTableVBR16: case FFT_SinCosTableVBR16:
@ -318,7 +320,7 @@ void ReorderToFreq4x(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *I
#ifdef REAL_SINCOSBRTABLE #ifdef REAL_SINCOSBRTABLE
/* /*
* Forward FFT routine. Must call InitializeFFT(fftlen) first! * Forward FFT routine. Must call GetFFT(fftlen) first!
* *
* Note: Output is BIT-REVERSED! so you must use the BitReversed to * Note: Output is BIT-REVERSED! so you must use the BitReversed to
* get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ] * get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ]
@ -335,7 +337,7 @@ void ReorderToFreq4x(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *I
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void RealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h) void RealFFTf1xSinCosBRTable(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *sptr; fft_type *sptr;
@ -360,7 +362,7 @@ void RealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
{ {
A = buffer; A = buffer;
B = buffer + ButterfliesPerGroup * 2; B = buffer + ButterfliesPerGroup * 2;
sptr = h->SinTable; sptr = h->SinTable.get();
while(A < endptr1) while(A < endptr1)
{ {
@ -383,8 +385,8 @@ void RealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
ButterfliesPerGroup >>= 1; ButterfliesPerGroup >>= 1;
} }
/* Massage output to get the output for a real input sequence. */ /* Massage output to get the output for a real input sequence. */
br1 = h->BitReversed + 1; br1 = h->BitReversed.get() + 1;
br2 = h->BitReversed + h->Points - 1; br2 = h->BitReversed.get() + h->Points - 1;
while(br1 < br2) while(br1 < br2)
{ {
@ -425,7 +427,7 @@ void RealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -437,7 +439,7 @@ void RealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h) void InverseRealFFTf1xSinCosBRTable(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *sptr; fft_type *sptr;
@ -451,7 +453,7 @@ void InverseRealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
/* Massage input to get the input for a real output sequence. */ /* Massage input to get the input for a real output sequence. */
A = buffer + 2; A = buffer + 2;
B = buffer + h->Points * 2 - 2; B = buffer + h->Points * 2 - 2;
br1 = h->BitReversed + 1; br1 = h->BitReversed.get() + 1;
while(A < B) while(A < B)
{ {
sin=h->SinTable[*br1]; sin=h->SinTable[*br1];
@ -497,7 +499,7 @@ void InverseRealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
{ {
A = buffer; A = buffer;
B = buffer + ButterfliesPerGroup * 2; B = buffer + ButterfliesPerGroup * 2;
sptr = h->SinTable; sptr = h->SinTable.get();
while(A < endptr1) while(A < endptr1)
{ {
@ -520,7 +522,7 @@ void InverseRealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
} }
} }
void ReorderToFreq1xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq1xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
// Copy the data into the real and imaginary outputs // Copy the data into the real and imaginary outputs
for(size_t i = 1; i < hFFT->Points; i++) { for(size_t i = 1; i < hFFT->Points; i++) {
@ -533,7 +535,7 @@ void ReorderToFreq1xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *RealOut
ImagOut[hFFT->Points] = 0; ImagOut[hFFT->Points] = 0;
} }
void ReorderToTime1xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime1xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
// Copy the data into the real outputs // Copy the data into the real outputs
for(size_t i = 0; i < hFFT->Points; i++) { for(size_t i = 0; i < hFFT->Points; i++) {
@ -543,7 +545,7 @@ void ReorderToTime1xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut
} }
// 4x processing simd // 4x processing simd
void RealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h) void RealFFTf4xSinCosBRTable(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -571,7 +573,7 @@ void RealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
{ {
A = localBuffer; A = localBuffer;
B = &localBuffer[ButterfliesPerGroup * 2]; B = &localBuffer[ButterfliesPerGroup * 2];
sptr = h->SinTable; sptr = h->SinTable.get();
while(A < endptr1) while(A < endptr1)
{ {
sin = _mm_set1_ps(*(sptr++)); sin = _mm_set1_ps(*(sptr++));
@ -637,7 +639,7 @@ void RealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -649,7 +651,7 @@ void RealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h) void InverseRealFFTf4xSinCosBRTable(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -717,7 +719,7 @@ void InverseRealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
{ {
A = localBuffer; A = localBuffer;
B = localBuffer + ButterfliesPerGroup * 2; B = localBuffer + ButterfliesPerGroup * 2;
sptr = h->SinTable; sptr = h->SinTable.get();
while(A < endptr1) while(A < endptr1)
{ {
sin = _mm_set1_ps(*(sptr++)); sin = _mm_set1_ps(*(sptr++));
@ -739,7 +741,7 @@ void InverseRealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
} }
} }
void ReorderToFreq4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq4xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
__m128 *localRealOut=(__m128 *)RealOut; __m128 *localRealOut=(__m128 *)RealOut;
@ -758,7 +760,7 @@ void ReorderToFreq4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *RealOut
localImagOut[hFFT->Points] = _mm_set1_ps(0.0); localImagOut[hFFT->Points] = _mm_set1_ps(0.0);
} }
void ReorderToTime4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime4xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
__m128 *localTimeOut=(__m128 *)TimeOut; __m128 *localTimeOut=(__m128 *)TimeOut;
@ -777,7 +779,7 @@ void ReorderToTime4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut
#ifdef REAL_SINCOSTABLE_VBR16 #ifdef REAL_SINCOSTABLE_VBR16
/* /*
* Forward FFT routine. Must call InitializeFFT(fftlen) first! * Forward FFT routine. Must call GetFFT(fftlen) first!
* *
* Note: Output is BIT-REVERSED! so you must use the BitReversed to * Note: Output is BIT-REVERSED! so you must use the BitReversed to
* get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ] * get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ]
@ -794,7 +796,7 @@ void ReorderToTime4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void RealFFTf1xSinCosTableVBR16(fft_type *buffer,HFFT h) void RealFFTf1xSinCosTableVBR16(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *endptr1,*endptr2; fft_type *endptr1,*endptr2;
@ -880,7 +882,7 @@ void RealFFTf1xSinCosTableVBR16(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -892,7 +894,7 @@ void RealFFTf1xSinCosTableVBR16(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf1xSinCosTableVBR16(fft_type *buffer,HFFT h) void InverseRealFFTf1xSinCosTableVBR16(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *endptr1,*endptr2; fft_type *endptr1,*endptr2;
@ -907,7 +909,7 @@ void InverseRealFFTf1xSinCosTableVBR16(fft_type *buffer,HFFT h)
/* Massage input to get the input for a real output sequence. */ /* Massage input to get the input for a real output sequence. */
A = buffer + 2; A = buffer + 2;
B = buffer + h->Points * 2 - 2; B = buffer + h->Points * 2 - 2;
br1 = h->BitReversed + 1; br1 = h->BitReversed.get() + 1;
br1Index = 1; //h->BitReversed + 1; br1Index = 1; //h->BitReversed + 1;
while(A < B) while(A < B)
{ {
@ -980,7 +982,7 @@ void InverseRealFFTf1xSinCosTableVBR16(fft_type *buffer,HFFT h)
} }
} }
void ReorderToTime1xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime1xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
// Copy the data into the real outputs // Copy the data into the real outputs
for(size_t i = 0;i < hFFT->Points; i++) { for(size_t i = 0;i < hFFT->Points; i++) {
@ -991,7 +993,7 @@ void ReorderToTime1xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *Time
} }
} }
void ReorderToFreq1xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq1xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
// Copy the data into the real and imaginary outputs // Copy the data into the real and imaginary outputs
for(size_t i = 1; i < hFFT->Points; i++) { for(size_t i = 1; i < hFFT->Points; i++) {
@ -1007,7 +1009,7 @@ void ReorderToFreq1xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *Real
} }
// 4x processing simd // 4x processing simd
void RealFFTf4xSinCosTableVBR16(fft_type *buffer,HFFT h) void RealFFTf4xSinCosTableVBR16(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -1105,7 +1107,7 @@ void RealFFTf4xSinCosTableVBR16(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -1117,7 +1119,7 @@ void RealFFTf4xSinCosTableVBR16(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf4xSinCosTableVBR16(fft_type *buffer,HFFT h) void InverseRealFFTf4xSinCosTableVBR16(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -1210,7 +1212,7 @@ void InverseRealFFTf4xSinCosTableVBR16(fft_type *buffer,HFFT h)
} }
} }
void ReorderToTime4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime4xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
__m128 *localBuffer = (__m128 *)buffer; __m128 *localBuffer = (__m128 *)buffer;
__m128 *localTimeOut = (__m128 *)TimeOut; __m128 *localTimeOut = (__m128 *)TimeOut;
@ -1223,7 +1225,7 @@ void ReorderToTime4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *Time
} }
} }
void ReorderToFreq4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq4xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
__m128 *localBuffer = (__m128 *)buffer; __m128 *localBuffer = (__m128 *)buffer;
__m128 *localRealOut = (__m128 *)RealOut; __m128 *localRealOut = (__m128 *)RealOut;
@ -1247,7 +1249,7 @@ void ReorderToFreq4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *Real
#ifdef REAL_SINCOSTABLE_BR16 #ifdef REAL_SINCOSTABLE_BR16
/* /*
* Forward FFT routine. Must call InitializeFFT(fftlen) first! * Forward FFT routine. Must call GetFFT(fftlen) first!
* *
* Note: Output is BIT-REVERSED! so you must use the BitReversed to * Note: Output is BIT-REVERSED! so you must use the BitReversed to
* get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ] * get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ]
@ -1264,7 +1266,7 @@ void ReorderToFreq4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *Real
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void RealFFTf1xSinCosTableBR16(fft_type *buffer,HFFT h) void RealFFTf1xSinCosTableBR16(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *endptr1, *endptr2; fft_type *endptr1, *endptr2;
@ -1354,7 +1356,7 @@ void RealFFTf1xSinCosTableBR16(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -1366,7 +1368,7 @@ void RealFFTf1xSinCosTableBR16(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf1xSinCosTableBR16(fft_type *buffer,HFFT h) void InverseRealFFTf1xSinCosTableBR16(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *endptr1,*endptr2; fft_type *endptr1,*endptr2;
@ -1453,7 +1455,7 @@ void InverseRealFFTf1xSinCosTableBR16(fft_type *buffer,HFFT h)
} }
} }
void ReorderToFreq1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq1xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
int bitReverseShift=16-hFFT->pow2Bits; int bitReverseShift=16-hFFT->pow2Bits;
// Copy the data into the real and imaginary outputs // Copy the data into the real and imaginary outputs
@ -1470,7 +1472,7 @@ void ReorderToFreq1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealO
ImagOut[hFFT->Points] = 0; ImagOut[hFFT->Points] = 0;
} }
void ReorderToTime1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime1xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
int bitReverseShift=16-hFFT->pow2Bits; int bitReverseShift=16-hFFT->pow2Bits;
// Copy the data into the real outputs // Copy the data into the real outputs
@ -1484,7 +1486,7 @@ void ReorderToTime1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeO
} }
// 4x processing simd // 4x processing simd
void RealFFTf4xSinCosTableBR16(fft_type *buffer,HFFT h) void RealFFTf4xSinCosTableBR16(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -1586,7 +1588,7 @@ void RealFFTf4xSinCosTableBR16(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -1598,7 +1600,7 @@ void RealFFTf4xSinCosTableBR16(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf4xSinCosTableBR16(fft_type *buffer,HFFT h) void InverseRealFFTf4xSinCosTableBR16(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -1692,7 +1694,7 @@ void InverseRealFFTf4xSinCosTableBR16(fft_type *buffer,HFFT h)
} }
} }
void ReorderToTime4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime4xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
__m128 *localBuffer = (__m128 *)buffer; __m128 *localBuffer = (__m128 *)buffer;
__m128 *localTimeOut = (__m128 *)TimeOut; __m128 *localTimeOut = (__m128 *)TimeOut;
@ -1708,7 +1710,7 @@ void ReorderToTime4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeO
} }
} }
void ReorderToFreq4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq4xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
__m128 *localBuffer = (__m128 *)buffer; __m128 *localBuffer = (__m128 *)buffer;
__m128 *localRealOut = (__m128 *)RealOut; __m128 *localRealOut = (__m128 *)RealOut;
@ -1734,7 +1736,7 @@ void ReorderToFreq4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealO
#ifdef FAST_MATH_BR24 #ifdef FAST_MATH_BR24
/* /*
* Forward FFT routine. Must call InitializeFFT(fftlen) first! * Forward FFT routine. Must call GetFFT(fftlen) first!
* *
* Note: Output is BIT-REVERSED! so you must use the BitReversed to * Note: Output is BIT-REVERSED! so you must use the BitReversed to
* get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ] * get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ]
@ -1751,7 +1753,7 @@ void ReorderToFreq4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealO
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void RealFFTf1xFastMathBR24(fft_type *buffer,HFFT h) void RealFFTf1xFastMathBR24(fft_type *buffer, FFTParam *h)
{ {
fft_type *A, *B; fft_type *A, *B;
fft_type *endptr1, *endptr2; fft_type *endptr1, *endptr2;
@ -1886,7 +1888,7 @@ void RealFFTf1xFastMathBR24(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -1898,7 +1900,7 @@ void RealFFTf1xFastMathBR24(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf1xFastMathBR24(fft_type *buffer,HFFT h) void InverseRealFFTf1xFastMathBR24(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *endptr1,*endptr2; fft_type *endptr1,*endptr2;
@ -2019,7 +2021,7 @@ void InverseRealFFTf1xFastMathBR24(fft_type *buffer,HFFT h)
} }
} }
void ReorderToFreq1xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq1xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
int bitReverseShift = 24 - hFFT->pow2Bits; int bitReverseShift = 24 - hFFT->pow2Bits;
// Copy the data into the real and imaginary outputs // Copy the data into the real and imaginary outputs
@ -2037,7 +2039,7 @@ void ReorderToFreq1xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *RealOut,
ImagOut[hFFT->Points] = 0; ImagOut[hFFT->Points] = 0;
} }
void ReorderToTime1xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime1xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
int bitReverseShift = 24 - hFFT->pow2Bits; int bitReverseShift = 24 - hFFT->pow2Bits;
// Copy the data into the real outputs // Copy the data into the real outputs
@ -2050,7 +2052,7 @@ void ReorderToTime1xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut)
} }
} }
void RealFFTf4xFastMathBR24(fft_type *buffer,HFFT h) void RealFFTf4xFastMathBR24(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -2186,7 +2188,7 @@ void RealFFTf4xFastMathBR24(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -2198,7 +2200,7 @@ void RealFFTf4xFastMathBR24(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf4xFastMathBR24(fft_type *buffer,HFFT h) void InverseRealFFTf4xFastMathBR24(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -2325,7 +2327,7 @@ void InverseRealFFTf4xFastMathBR24(fft_type *buffer,HFFT h)
} }
} }
void ReorderToFreq4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq4xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
__m128 *localBuffer = (__m128 *)buffer; __m128 *localBuffer = (__m128 *)buffer;
__m128 *localRealOut = (__m128 *)RealOut; __m128 *localRealOut = (__m128 *)RealOut;
@ -2347,7 +2349,7 @@ void ReorderToFreq4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *RealOut,
localImagOut[hFFT->Points] = _mm_set1_ps(0.0); localImagOut[hFFT->Points] = _mm_set1_ps(0.0);
} }
void ReorderToTime4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime4xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
__m128 *localBuffer = (__m128 *)buffer; __m128 *localBuffer = (__m128 *)buffer;
__m128 *localTimeOut = (__m128 *)TimeOut; __m128 *localTimeOut = (__m128 *)TimeOut;
@ -2369,7 +2371,7 @@ void ReorderToTime4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut)
#ifdef FAST_MATH_BR16 #ifdef FAST_MATH_BR16
/* /*
* Forward FFT routine. Must call InitializeFFT(fftlen) first! * Forward FFT routine. Must call GetFFT(fftlen) first!
* *
* Note: Output is BIT-REVERSED! so you must use the BitReversed to * Note: Output is BIT-REVERSED! so you must use the BitReversed to
* get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ] * get legible output, (i.e. Real_i = buffer[ h->BitReversed[i] ]
@ -2386,7 +2388,7 @@ void ReorderToTime4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void RealFFTf1xFastMathBR16(fft_type *buffer,HFFT h) void RealFFTf1xFastMathBR16(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *endptr1,*endptr2; fft_type *endptr1,*endptr2;
@ -2517,7 +2519,7 @@ void RealFFTf1xFastMathBR16(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -2529,7 +2531,7 @@ void RealFFTf1xFastMathBR16(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf1xFastMathBR16(fft_type *buffer,HFFT h) void InverseRealFFTf1xFastMathBR16(fft_type *buffer, FFTParam *h)
{ {
fft_type *A,*B; fft_type *A,*B;
fft_type *endptr1,*endptr2; fft_type *endptr1,*endptr2;
@ -2650,7 +2652,7 @@ void InverseRealFFTf1xFastMathBR16(fft_type *buffer,HFFT h)
} }
} }
void ReorderToFreq1xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq1xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
int bitReverseShift = 16 - hFFT->pow2Bits; int bitReverseShift = 16 - hFFT->pow2Bits;
// Copy the data into the real and imaginary outputs // Copy the data into the real and imaginary outputs
@ -2667,7 +2669,7 @@ void ReorderToFreq1xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut,
ImagOut[hFFT->Points] = 0; ImagOut[hFFT->Points] = 0;
} }
void ReorderToTime1xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime1xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
int bitReverseShift=16-hFFT->pow2Bits; int bitReverseShift=16-hFFT->pow2Bits;
// Copy the data into the real outputs // Copy the data into the real outputs
@ -2680,7 +2682,7 @@ void ReorderToTime1xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut)
} }
} }
void RealFFTf4xFastMathBR16(fft_type *buffer,HFFT h) void RealFFTf4xFastMathBR16(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer = (__m128 *)buffer; __m128 *localBuffer = (__m128 *)buffer;
@ -2816,7 +2818,7 @@ void RealFFTf4xFastMathBR16(fft_type *buffer,HFFT h)
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] * get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) * wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
* Input is in normal order, interleaved (real,imaginary) complex data * Input is in normal order, interleaved (real,imaginary) complex data
* You must call InitializeFFT(fftlen) first to initialize some buffers! * You must call GetFFT(fftlen) first to initialize some buffers!
* *
* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin * Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin
* - this can be done because both values will always be real only * - this can be done because both values will always be real only
@ -2828,7 +2830,7 @@ void RealFFTf4xFastMathBR16(fft_type *buffer,HFFT h)
* values would be similar in amplitude to the input values, which is * values would be similar in amplitude to the input values, which is
* good when using fixed point arithmetic) * good when using fixed point arithmetic)
*/ */
void InverseRealFFTf4xFastMathBR16(fft_type *buffer,HFFT h) void InverseRealFFTf4xFastMathBR16(fft_type *buffer, FFTParam *h)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
@ -2955,7 +2957,7 @@ void InverseRealFFTf4xFastMathBR16(fft_type *buffer,HFFT h)
} }
} }
void ReorderToFreq4xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) void ReorderToFreq4xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
__m128 *localRealOut=(__m128 *)RealOut; __m128 *localRealOut=(__m128 *)RealOut;
@ -2977,7 +2979,7 @@ void ReorderToFreq4xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut,
localImagOut[hFFT->Points] = _mm_set1_ps(0.0); localImagOut[hFFT->Points] = _mm_set1_ps(0.0);
} }
void ReorderToTime4xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) void ReorderToTime4xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut)
{ {
__m128 *localBuffer=(__m128 *)buffer; __m128 *localBuffer=(__m128 *)buffer;
__m128 *localTimeOut=(__m128 *)TimeOut; __m128 *localTimeOut=(__m128 *)TimeOut;

View File

@ -16,64 +16,64 @@ enum {
}; };
/* wrapper funcitons. If passed -1 function choice will be made locally */ /* wrapper funcitons. If passed -1 function choice will be made locally */
void RealFFTf1x(fft_type *,HFFT, int functionType=-1); void RealFFTf1x(fft_type *, FFTParam*, int functionType=-1);
void InverseRealFFTf1x(fft_type *,HFFT, int functionType=-1); void InverseRealFFTf1x(fft_type *, FFTParam*, int functionType=-1);
void ReorderToTime1x(HFFT hFFT, fft_type *buffer, fft_type *TimeOut, int functionType=-1); void ReorderToTime1x(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut, int functionType=-1);
void ReorderToFreq1x(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType=-1); void ReorderToFreq1x(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType=-1);
void RealFFTf4x(fft_type *,HFFT, int functionType=-1); void RealFFTf4x(fft_type *, FFTParam *, int functionType=-1);
void InverseRealFFTf4x(fft_type *,HFFT, int functionType=-1); void InverseRealFFTf4x(fft_type *, FFTParam *, int functionType=-1);
void ReorderToTime4x(HFFT hFFT, fft_type *buffer, fft_type *TimeOut, int functionType=-1); void ReorderToTime4x(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut, int functionType=-1);
void ReorderToFreq4x(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType=-1); void ReorderToFreq4x(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType=-1);
/* SinCosBRTable versions */ /* SinCosBRTable versions */
void RealFFTf1xSinCosBRTable(fft_type *,HFFT); void RealFFTf1xSinCosBRTable(fft_type *, FFTParam*);
void InverseRealFFTf1xSinCosBRTable(fft_type *,HFFT); void InverseRealFFTf1xSinCosBRTable(fft_type *, FFTParam*);
void ReorderToTime1xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime1xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq1xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq1xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
void RealFFTf4xSinCosBRTable(fft_type *,HFFT); void RealFFTf4xSinCosBRTable(fft_type *, FFTParam *);
void InverseRealFFTf4xSinCosBRTable(fft_type *,HFFT); void InverseRealFFTf4xSinCosBRTable(fft_type *, FFTParam *);
void ReorderToTime4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime4xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq4xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
/* Fast Math BR16 versions */ /* Fast Math BR16 versions */
void RealFFTf1xFastMathBR16(fft_type *,HFFT); void RealFFTf1xFastMathBR16(fft_type *, FFTParam*);
void InverseRealFFTf1xFastMathBR16(fft_type *,HFFT); void InverseRealFFTf1xFastMathBR16(fft_type *, FFTParam*);
void ReorderToTime1xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime1xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq1xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq1xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
void RealFFTf4xFastMathBR16(fft_type *,HFFT); void RealFFTf4xFastMathBR16(fft_type *, FFTParam *);
void InverseRealFFTf4xFastMathBR16(fft_type *,HFFT); void InverseRealFFTf4xFastMathBR16(fft_type *, FFTParam *);
void ReorderToTime4xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime4xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq4xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq4xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
/* Fast Math BR24 versions */ /* Fast Math BR24 versions */
void RealFFTf1xFastMathBR24(fft_type *,HFFT); void RealFFTf1xFastMathBR24(fft_type *, FFTParam*);
void InverseRealFFTf1xFastMathBR24(fft_type *,HFFT); void InverseRealFFTf1xFastMathBR24(fft_type *, FFTParam*);
void ReorderToTime1xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime1xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq1xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq1xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
void RealFFTf4xFastMathBR24(fft_type *,HFFT); void RealFFTf4xFastMathBR24(fft_type *, FFTParam *);
void InverseRealFFTf4xFastMathBR24(fft_type *,HFFT); void InverseRealFFTf4xFastMathBR24(fft_type *, FFTParam *);
void ReorderToTime4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime4xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq4xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
/* SinCosTable virtual BR versions */ /* SinCosTable virtual BR versions */
void RealFFTf1xSinCosTableVBR16(fft_type *,HFFT); void RealFFTf1xSinCosTableVBR16(fft_type *, FFTParam*);
void InverseRealFFTf1xSinCosTableVBR16(fft_type *,HFFT); void InverseRealFFTf1xSinCosTableVBR16(fft_type *, FFTParam*);
void ReorderToTime1xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime1xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq1xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq1xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
void RealFFTf4xSinCosTableVBR16(fft_type *,HFFT); void RealFFTf4xSinCosTableVBR16(fft_type *, FFTParam *);
void InverseRealFFTf4xSinCosTableVBR16(fft_type *,HFFT); void InverseRealFFTf4xSinCosTableVBR16(fft_type *, FFTParam *);
void ReorderToTime4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime4xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq4xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
/* SinCosTable BR16 versions */ /* SinCosTable BR16 versions */
void RealFFTf1xSinCosTableBR16(fft_type *,HFFT); void RealFFTf1xSinCosTableBR16(fft_type *, FFTParam*);
void InverseRealFFTf1xSinCosTableBR16(fft_type *,HFFT); void InverseRealFFTf1xSinCosTableBR16(fft_type *, FFTParam*);
void ReorderToTime1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime1xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq1xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
void RealFFTf4xSinCosTableBR16(fft_type *,HFFT); void RealFFTf4xSinCosTableBR16(fft_type *, FFTParam *);
void InverseRealFFTf4xSinCosTableBR16(fft_type *,HFFT); void InverseRealFFTf4xSinCosTableBR16(fft_type *, FFTParam *);
void ReorderToTime4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); void ReorderToTime4xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
void ReorderToFreq4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); void ReorderToFreq4xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
void TableUsage(int iMask); void TableUsage(int iMask);

View File

@ -41,13 +41,11 @@ Resample::Resample(const bool useBestMethod, const double dMinFactor, const doub
mbWantConstRateResampling = false; // variable rate resampling mbWantConstRateResampling = false; // variable rate resampling
q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR); q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR);
} }
mHandle = (void *)soxr_create(1, dMinFactor, 1, 0, 0, &q_spec, 0); mHandle.reset(soxr_create(1, dMinFactor, 1, 0, 0, &q_spec, 0));
} }
Resample::~Resample() Resample::~Resample()
{ {
soxr_delete((soxr_t)mHandle);
mHandle = NULL;
} }
int Resample::GetNumMethods() { return 4; } int Resample::GetNumMethods() { return 4; }
@ -85,16 +83,16 @@ std::pair<size_t, size_t>
size_t idone, odone; size_t idone, odone;
if (mbWantConstRateResampling) if (mbWantConstRateResampling)
{ {
soxr_process((soxr_t)mHandle, soxr_process(mHandle.get(),
inBuffer , (lastFlag? ~inBufferLen : inBufferLen), &idone, inBuffer , (lastFlag? ~inBufferLen : inBufferLen), &idone,
outBuffer, outBufferLen, &odone); outBuffer, outBufferLen, &odone);
} }
else else
{ {
soxr_set_io_ratio((soxr_t)mHandle, 1/factor, 0); soxr_set_io_ratio(mHandle.get(), 1/factor, 0);
inBufferLen = lastFlag? ~inBufferLen : inBufferLen; inBufferLen = lastFlag? ~inBufferLen : inBufferLen;
soxr_process((soxr_t)mHandle, soxr_process(mHandle.get(),
inBuffer , inBufferLen , &idone, inBuffer , inBufferLen , &idone,
outBuffer, outBufferLen, &odone); outBuffer, outBufferLen, &odone);
} }

View File

@ -14,11 +14,19 @@
#include "Audacity.h" #include "Audacity.h"
#include "MemoryX.h"
#include <wx/intl.h> #include <wx/intl.h>
#include <wx/string.h> #include <wx/string.h>
#include "SampleFormat.h" #include "SampleFormat.h"
struct soxr;
extern "C" void soxr_delete(soxr*);
struct soxr_deleter {
void operator () (soxr *p) const { if (p) soxr_delete(p); }
};
using soxrHandle = std::unique_ptr<soxr, soxr_deleter>;
class Resample final class Resample final
{ {
public: public:
@ -78,7 +86,7 @@ class Resample final
protected: protected:
int mMethod; // resampler-specific enum for resampling method int mMethod; // resampler-specific enum for resampling method
void* mHandle; // constant-rate or variable-rate resampler (XOR per instance) soxrHandle mHandle; // constant-rate or variable-rate resampler (XOR per instance)
bool mbWantConstRateResampling; bool mbWantConstRateResampling;
}; };

View File

@ -74,16 +74,6 @@ const wxChar *GetSampleFormatStr(sampleFormat format)
return wxT("Unknown format"); // compiler food return wxT("Unknown format"); // compiler food
} }
AUDACITY_DLL_API samplePtr NewSamples(size_t count, sampleFormat format)
{
return (samplePtr)malloc(count * SAMPLE_SIZE(format));
}
AUDACITY_DLL_API void DeleteSamples(samplePtr p)
{
free(p);
}
// TODO: Risky? Assumes 0.0f is represented by 0x00000000; // TODO: Risky? Assumes 0.0f is represented by 0x00000000;
void ClearSamples(samplePtr src, sampleFormat format, void ClearSamples(samplePtr src, sampleFormat format,
size_t start, size_t len) size_t start, size_t len)

View File

@ -49,10 +49,6 @@ const wxChar *GetSampleFormatStr(sampleFormat format);
// Allocating/Freeing Samples // Allocating/Freeing Samples
// //
AUDACITY_DLL_API samplePtr NewSamples(size_t count, sampleFormat format);
AUDACITY_DLL_API void DeleteSamples(samplePtr p);
// RAII version of above
class SampleBuffer { class SampleBuffer {
public: public:
@ -60,7 +56,7 @@ public:
: mPtr(0) : mPtr(0)
{} {}
SampleBuffer(size_t count, sampleFormat format) SampleBuffer(size_t count, sampleFormat format)
: mPtr(NewSamples(count, format)) : mPtr((samplePtr)malloc(count * SAMPLE_SIZE(format)))
{} {}
~SampleBuffer() ~SampleBuffer()
{ {
@ -71,14 +67,14 @@ public:
SampleBuffer &Allocate(size_t count, sampleFormat format) SampleBuffer &Allocate(size_t count, sampleFormat format)
{ {
Free(); Free();
mPtr = NewSamples(count, format); mPtr = (samplePtr)malloc(count * SAMPLE_SIZE(format));
return *this; return *this;
} }
void Free() void Free()
{ {
DeleteSamples(mPtr); free(mPtr);
mPtr = 0; mPtr = 0;
} }

View File

@ -347,7 +347,9 @@ wxImage ThemeBase::MaskedImage( char const ** pXpm, char const ** pMask )
// unsigned char *src = Img1.GetData(); // unsigned char *src = Img1.GetData();
unsigned char *mk = Img2.GetData(); unsigned char *mk = Img2.GetData();
unsigned char *alpha = (unsigned char*)malloc( nBytes ); //wxImage::setAlpha requires memory allocated with malloc, not new
MallocString<unsigned char> alpha{
static_cast<unsigned char*>(malloc( nBytes )) };
// Extract alpha channel from second XPM. // Extract alpha channel from second XPM.
for(i=0;i<nBytes;i++) for(i=0;i<nBytes;i++)
@ -356,7 +358,7 @@ wxImage ThemeBase::MaskedImage( char const ** pXpm, char const ** pMask )
mk+=3; mk+=3;
} }
Img1.SetAlpha( alpha); Img1.SetAlpha( alpha.release() );
//dmazzoni: the top line does not work on wxGTK //dmazzoni: the top line does not work on wxGTK
//wxBitmap Result( Img1, 32 ); //wxBitmap Result( Img1, 32 );

View File

@ -273,7 +273,8 @@ protected:
}; };
static void ComputeSpectrumUsingRealFFTf static void ComputeSpectrumUsingRealFFTf
(float * __restrict buffer, HFFT hFFT, const float * __restrict window, size_t len, float * __restrict out) (float * __restrict buffer, const FFTParam *hFFT,
const float * __restrict window, size_t len, float * __restrict out)
{ {
size_t i; size_t i;
if(len > hFFT->Points * 2) if(len > hFFT->Points * 2)
@ -924,7 +925,7 @@ bool SpecCache::CalculateOneSpectrum
} }
else if (reassignment) { else if (reassignment) {
static const double epsilon = 1e-16; static const double epsilon = 1e-16;
const HFFT hFFT = settings.hFFT; const auto hFFT = settings.hFFT.get();
float *const scratch2 = scratch + fftLen; float *const scratch2 = scratch + fftLen;
std::copy(scratch, scratch2, scratch2); std::copy(scratch, scratch2, scratch2);
@ -1024,7 +1025,7 @@ bool SpecCache::CalculateOneSpectrum
// This function mutates useBuffer // This function mutates useBuffer
ComputeSpectrumUsingRealFFTf ComputeSpectrumUsingRealFFTf
(useBuffer, settings.hFFT, settings.window.get(), fftLen, results); (useBuffer, settings.hFFT.get(), settings.window.get(), fftLen, results);
if (!gainFactors.empty()) { if (!gainFactors.empty()) {
// Apply a frequency-dependant gain factor // Apply a frequency-dependant gain factor
for (size_t ii = 0; ii < nBins; ++ii) for (size_t ii = 0; ii < nBins; ++ii)
@ -1160,7 +1161,7 @@ void SpecCache::Populate
#endif #endif
for (auto xx = lowerBoundX; xx < upperBoundX; ++xx) { for (auto xx = lowerBoundX; xx < upperBoundX; ++xx) {
float *const results = &freq[nBins * xx]; float *const results = &freq[nBins * xx];
const HFFT hFFT = settings.hFFT; const auto hFFT = settings.hFFT.get();
for (size_t ii = 0; ii < nBins; ++ii) { for (size_t ii = 0; ii < nBins; ++ii) {
float &power = results[ii]; float &power = results[ii];
if (power <= 0) if (power <= 0)

View File

@ -220,7 +220,7 @@ EffectEqualization::EffectEqualization()
mCurve = NULL; mCurve = NULL;
mPanel = NULL; mPanel = NULL;
hFFT = InitializeFFT(windowSize); hFFT = GetFFT(windowSize);
SetLinearEffectFlag(true); SetLinearEffectFlag(true);
@ -282,9 +282,6 @@ EffectEqualization::EffectEqualization()
EffectEqualization::~EffectEqualization() EffectEqualization::~EffectEqualization()
{ {
if(hFFT)
EndFFT(hFFT);
hFFT = NULL;
} }
// IdentInterface implementation // IdentInterface implementation
@ -1319,7 +1316,7 @@ void EffectEqualization::Filter(size_t len, float *buffer)
{ {
float re,im; float re,im;
// Apply FFT // Apply FFT
RealFFTf(buffer, hFFT); RealFFTf(buffer, hFFT.get());
//FFT(len, false, inr, NULL, outr, outi); //FFT(len, false, inr, NULL, outr, outi);
// Apply filter // Apply filter
@ -1336,8 +1333,8 @@ void EffectEqualization::Filter(size_t len, float *buffer)
mFFTBuffer[1] = buffer[1] * mFilterFuncR[len/2]; mFFTBuffer[1] = buffer[1] * mFilterFuncR[len/2];
// Inverse FFT and normalization // Inverse FFT and normalization
InverseRealFFTf(mFFTBuffer.get(), hFFT); InverseRealFFTf(mFFTBuffer.get(), hFFT.get());
ReorderToTime(hFFT, mFFTBuffer.get(), buffer); ReorderToTime(hFFT.get(), mFFTBuffer.get(), buffer);
} }
// //

View File

@ -158,7 +158,7 @@ void * malloc_simd(const size_t size)
#endif #endif
} }
void free_simd(void* mem) void free_simd::operator() (void* mem) const
{ {
#if defined WIN32 // WIN32 #if defined WIN32 // WIN32
_aligned_free(mem); _aligned_free(mem);
@ -169,7 +169,7 @@ void free_simd(void* mem)
EffectEqualization48x::EffectEqualization48x(): EffectEqualization48x::EffectEqualization48x():
mThreadCount(0),mFilterSize(0),mWindowSize(0),mBlockSize(0),mWorkerDataCount(0),mBlocksPerBuffer(20), mThreadCount(0),mFilterSize(0),mWindowSize(0),mBlockSize(0),mWorkerDataCount(0),mBlocksPerBuffer(20),
mScratchBufferSize(0),mSubBufferSize(0),mBigBuffer(NULL),mThreaded(false), mScratchBufferSize(0),mSubBufferSize(0),mThreaded(false),
mBenching(false),mBufferCount(0) mBenching(false),mBufferCount(0)
{ {
} }
@ -211,7 +211,7 @@ bool EffectEqualization48x::AllocateBuffersWorkers(int nThreads)
mScratchBufferSize=mWindowSize*3*sizeof(float)*mBufferCount; // 3 window size blocks of instruction size mScratchBufferSize=mWindowSize*3*sizeof(float)*mBufferCount; // 3 window size blocks of instruction size
mSubBufferSize=mBlockSize*(mBufferCount*(mBlocksPerBuffer-1)); // we are going to do a full block overlap mSubBufferSize=mBlockSize*(mBufferCount*(mBlocksPerBuffer-1)); // we are going to do a full block overlap
mBigBuffer=(float *)malloc_simd(sizeof(float)*(mSubBufferSize+mFilterSize+mScratchBufferSize)*mWorkerDataCount); // we run over by filtersize mBigBuffer.reset( (float *)malloc_simd(sizeof(float) * (mSubBufferSize + mFilterSize + mScratchBufferSize) * mWorkerDataCount) ); // we run over by filtersize
// fill the bufferInfo // fill the bufferInfo
mBufferInfo.reinit(mWorkerDataCount); mBufferInfo.reinit(mWorkerDataCount);
for(int i=0;i<mWorkerDataCount;i++) { for(int i=0;i<mWorkerDataCount;i++) {
@ -250,8 +250,7 @@ bool EffectEqualization48x::FreeBuffersWorkers()
mWorkerDataCount=0; mWorkerDataCount=0;
} }
mBufferInfo.reset(); mBufferInfo.reset();
free_simd(mBigBuffer); mBigBuffer.reset();
mBigBuffer=NULL;
return true; return true;
} }
@ -672,8 +671,8 @@ bool EffectEqualization48x::ProcessOne1x(int count, WaveTrack * t,
output->Append((samplePtr)&mBigBuffer[(bigRun?mBlockSize:0)+(mFilterSize>>1)], floatSample, subBufferSize-((bigRun?mBlockSize:0)+(mFilterSize>>1))); output->Append((samplePtr)&mBigBuffer[(bigRun?mBlockSize:0)+(mFilterSize>>1)], floatSample, subBufferSize-((bigRun?mBlockSize:0)+(mFilterSize>>1)));
} }
if(singleProcessLength && !bBreakLoop) { if(singleProcessLength && !bBreakLoop) {
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1)); ProcessBuffer(mBigBuffer.get(), mBigBuffer.get(), singleProcessLength+mBlockSize+(mFilterSize>>1));
output->Append((samplePtr)&mBigBuffer[bigRuns > 0 ? mBlockSize : 0], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); output->Append((samplePtr)&mBigBuffer[bigRuns > 0 ? mBlockSize : 0], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
} }
output->Flush(); output->Flush();
@ -688,7 +687,7 @@ void EffectEqualization48x::Filter1x(size_t len,
int i; int i;
float real, imag; float real, imag;
// Apply FFT // Apply FFT
RealFFTf1x(buffer, mEffectEqualization->hFFT); RealFFTf1x(buffer, mEffectEqualization->hFFT.get());
// Apply filter // Apply filter
// DC component is purely real // DC component is purely real
@ -721,8 +720,8 @@ void EffectEqualization48x::Filter1x(size_t len,
scratchBuffer[1] = buffer[1] * filterFuncR; scratchBuffer[1] = buffer[1] * filterFuncR;
// Inverse FFT and normalization // Inverse FFT and normalization
InverseRealFFTf1x(scratchBuffer, mEffectEqualization->hFFT); InverseRealFFTf1x(scratchBuffer, mEffectEqualization->hFFT.get());
ReorderToTime1x(mEffectEqualization->hFFT, scratchBuffer, buffer); ReorderToTime1x(mEffectEqualization->hFFT.get(), scratchBuffer, buffer);
} }
bool EffectEqualization48x::ProcessBuffer4x(BufferInfo *bufferInfo) bool EffectEqualization48x::ProcessBuffer4x(BufferInfo *bufferInfo)
@ -853,8 +852,8 @@ bool EffectEqualization48x::ProcessOne4x(int count, WaveTrack * t,
output->Append((samplePtr)&mBigBuffer[(bigRun?mBlockSize:0)+(mFilterSize>>1)], floatSample, subBufferSize-((bigRun?mBlockSize:0)+(mFilterSize>>1))); output->Append((samplePtr)&mBigBuffer[(bigRun?mBlockSize:0)+(mFilterSize>>1)], floatSample, subBufferSize-((bigRun?mBlockSize:0)+(mFilterSize>>1)));
} }
if(singleProcessLength && !bBreakLoop) { if(singleProcessLength && !bBreakLoop) {
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1)); ProcessBuffer(mBigBuffer.get(), mBigBuffer.get(), singleProcessLength+mBlockSize+(mFilterSize>>1));
output->Append((samplePtr)&mBigBuffer[bigRuns > 0 ? mBlockSize : 0], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); output->Append((samplePtr)&mBigBuffer[bigRuns > 0 ? mBlockSize : 0], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
// output->Append((samplePtr)&mBigBuffer[bigRuns?mBlockSize:0], floatSample, singleProcessLength); // output->Append((samplePtr)&mBigBuffer[bigRuns?mBlockSize:0], floatSample, singleProcessLength);
} }
@ -965,8 +964,8 @@ bool EffectEqualization48x::ProcessOne1x4xThreaded(int count, WaveTrack * t,
mDataMutex.Unlock(); // Get back in line for data mDataMutex.Unlock(); // Get back in line for data
} }
if(singleProcessLength && !bBreakLoop) { if(singleProcessLength && !bBreakLoop) {
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1)); ProcessBuffer(mBigBuffer.get(), mBigBuffer.get(), singleProcessLength+mBlockSize+(mFilterSize>>1));
output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
} }
output->Flush(); output->Flush();
@ -981,7 +980,7 @@ void EffectEqualization48x::Filter4x(size_t len,
int i; int i;
__m128 real128, imag128; __m128 real128, imag128;
// Apply FFT // Apply FFT
RealFFTf4x(buffer, mEffectEqualization->hFFT); RealFFTf4x(buffer, mEffectEqualization->hFFT.get());
// Apply filter // Apply filter
// DC component is purely real // DC component is purely real
@ -1015,8 +1014,8 @@ void EffectEqualization48x::Filter4x(size_t len,
localFFTBuffer[1] = _mm_mul_ps(localBuffer[1], filterFuncR); localFFTBuffer[1] = _mm_mul_ps(localBuffer[1], filterFuncR);
// Inverse FFT and normalization // Inverse FFT and normalization
InverseRealFFTf4x(scratchBuffer, mEffectEqualization->hFFT); InverseRealFFTf4x(scratchBuffer, mEffectEqualization->hFFT.get());
ReorderToTime4x(mEffectEqualization->hFFT, scratchBuffer, buffer); ReorderToTime4x(mEffectEqualization->hFFT.get(), scratchBuffer, buffer);
} }
#ifdef __AVX_ENABLED #ifdef __AVX_ENABLED
@ -1183,8 +1182,8 @@ bool EffectEqualization48x::ProcessOne8x(int count, WaveTrack * t,
output->Append((samplePtr)&mBigBuffer[(bigRun?mBlockSize:0)+(mFilterSize>>1)], floatSample, mSubBufferSize-((bigRun?mBlockSize:0)+(mFilterSize>>1))); output->Append((samplePtr)&mBigBuffer[(bigRun?mBlockSize:0)+(mFilterSize>>1)], floatSample, mSubBufferSize-((bigRun?mBlockSize:0)+(mFilterSize>>1)));
} }
if(singleProcessLength && !bBreakLoop) { if(singleProcessLength && !bBreakLoop) {
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1)); ProcessBuffer(mBigBuffer.get(), mBigBuffer.get(), singleProcessLength+mBlockSize+(mFilterSize>>1));
output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
} }
output->Flush(); output->Flush();
@ -1262,8 +1261,8 @@ bool EffectEqualization48x::ProcessOne8xThreaded(int count, WaveTrack * t,
mDataMutex.Unlock(); // Get back in line for data mDataMutex.Unlock(); // Get back in line for data
} }
if(singleProcessLength && !bBreakLoop) { if(singleProcessLength && !bBreakLoop) {
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1)); ProcessBuffer(mBigBuffer.get(), mBigBuffer.get(), singleProcessLength+mBlockSize+(mFilterSize>>1));
output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1)); output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
} }
output->Flush(); output->Flush();

View File

@ -32,6 +32,11 @@ Intrinsics (SSE/AVX) and Threaded Equalization
#define MATH_FUNCTION_AVX 16 #define MATH_FUNCTION_AVX 16
#define MATH_FUNCTION_SEGMENTED_CODE 32 #define MATH_FUNCTION_SEGMENTED_CODE 32
struct free_simd {
void operator () (void*) const;
};
using simd_floats = std::unique_ptr< float[], free_simd >;
// added by Andrew Hallendorff intrinsics processing // added by Andrew Hallendorff intrinsics processing
enum EQBufferStatus enum EQBufferStatus
{ {
@ -156,7 +161,7 @@ private:
size_t mBlocksPerBuffer; size_t mBlocksPerBuffer;
size_t mScratchBufferSize; size_t mScratchBufferSize;
size_t mSubBufferSize; size_t mSubBufferSize;
float *mBigBuffer; simd_floats mBigBuffer;
ArrayOf<BufferInfo> mBufferInfo; ArrayOf<BufferInfo> mBufferInfo;
wxMutex mDataMutex; wxMutex mDataMutex;
ArrayOf<EQWorker> mEQWorkers; ArrayOf<EQWorker> mEQWorkers;

View File

@ -640,7 +640,6 @@ bool EffectNoiseReduction::Process()
EffectNoiseReduction::Worker::~Worker() EffectNoiseReduction::Worker::~Worker()
{ {
EndFFT(hFFT);
} }
bool EffectNoiseReduction::Worker::Process bool EffectNoiseReduction::Worker::Process
@ -727,7 +726,7 @@ EffectNoiseReduction::Worker::Worker
, mSampleRate(sampleRate) , mSampleRate(sampleRate)
, mWindowSize(settings.WindowSize()) , mWindowSize(settings.WindowSize())
, hFFT(InitializeFFT(mWindowSize)) , hFFT(GetFFT(mWindowSize))
, mFFTBuffer(mWindowSize) , mFFTBuffer(mWindowSize)
, mInWaveBuffer(mWindowSize) , mInWaveBuffer(mWindowSize)
, mOutOverlapBuffer(mWindowSize) , mOutOverlapBuffer(mWindowSize)
@ -945,7 +944,7 @@ void EffectNoiseReduction::Worker::FillFirstHistoryWindow()
mFFTBuffer[ii] = mInWaveBuffer[ii] * mInWindow[ii]; mFFTBuffer[ii] = mInWaveBuffer[ii] * mInWindow[ii];
else else
memmove(&mFFTBuffer[0], &mInWaveBuffer[0], mWindowSize * sizeof(float)); memmove(&mFFTBuffer[0], &mInWaveBuffer[0], mWindowSize * sizeof(float));
RealFFTf(&mFFTBuffer[0], hFFT); RealFFTf(&mFFTBuffer[0], hFFT.get());
Record &record = *mQueue[0]; Record &record = *mQueue[0];
@ -1243,7 +1242,7 @@ void EffectNoiseReduction::Worker::ReduceNoise
} }
// Invert the FFT into the output buffer // Invert the FFT into the output buffer
InverseRealFFTf(&mFFTBuffer[0], hFFT); InverseRealFFTf(&mFFTBuffer[0], hFFT.get());
// Overlap-add // Overlap-add
if (mOutWindow.size() > 0) { if (mOutWindow.size() > 0) {

View File

@ -288,7 +288,7 @@ void EffectNoiseRemoval::Initialize()
mImagFFTs.reinit(mHistoryLen, mSpectrumSize); mImagFFTs.reinit(mHistoryLen, mSpectrumSize);
// Initialize the FFT // Initialize the FFT
hFFT = InitializeFFT(mWindowSize); hFFT = GetFFT(mWindowSize);
mFFTBuffer.reinit(mWindowSize); mFFTBuffer.reinit(mWindowSize);
mInWaveBuffer.reinit(mWindowSize); mInWaveBuffer.reinit(mWindowSize);
@ -307,7 +307,7 @@ void EffectNoiseRemoval::Initialize()
void EffectNoiseRemoval::Cleanup() void EffectNoiseRemoval::Cleanup()
{ {
EndFFT(hFFT); hFFT.reset();
if (mDoProfile) { if (mDoProfile) {
ApplyFreqSmoothing(mNoiseThreshold.get()); ApplyFreqSmoothing(mNoiseThreshold.get());
@ -374,8 +374,8 @@ void EffectNoiseRemoval::FillFirstHistoryWindow()
{ {
for(size_t i = 0; i < mWindowSize; i++) for(size_t i = 0; i < mWindowSize; i++)
mFFTBuffer[i] = mInWaveBuffer[i]; mFFTBuffer[i] = mInWaveBuffer[i];
RealFFTf(mFFTBuffer.get(), hFFT); RealFFTf(mFFTBuffer.get(), hFFT.get());
for(size_t i = 1; i < (mSpectrumSize-1); i++) { for(size_t i = 1; i + 1 < mSpectrumSize; i++) {
mRealFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i] ]; mRealFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i] ];
mImagFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i]+1]; mImagFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i]+1];
mSpectrums[0][i] = mRealFFTs[0][i]*mRealFFTs[0][i] + mImagFFTs[0][i]*mImagFFTs[0][i]; mSpectrums[0][i] = mRealFFTs[0][i]*mRealFFTs[0][i] + mImagFFTs[0][i]*mImagFFTs[0][i];
@ -502,7 +502,7 @@ void EffectNoiseRemoval::RemoveNoise()
mFFTBuffer[1] = mRealFFTs[out][mSpectrumSize-1] * mGains[out][mSpectrumSize-1]; mFFTBuffer[1] = mRealFFTs[out][mSpectrumSize-1] * mGains[out][mSpectrumSize-1];
// Invert the FFT into the output buffer // Invert the FFT into the output buffer
InverseRealFFTf(mFFTBuffer.get(), hFFT); InverseRealFFTf(mFFTBuffer.get(), hFFT.get());
// Overlap-add // Overlap-add
for(size_t j = 0; j < (mSpectrumSize-1); j++) { for(size_t j = 0; j < (mSpectrumSize-1); j++) {

View File

@ -78,8 +78,8 @@ FactoryPresets[] =
struct Reverb_priv_t struct Reverb_priv_t
{ {
reverb_t reverb; reverb_t reverb;
float *dry; float *dry {};
float *wet[2]; float *wet[2] { {}, {} };
}; };
// //
@ -171,7 +171,7 @@ bool EffectReverb::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelName
mNumChans = 2; mNumChans = 2;
} }
mP = (Reverb_priv_t *) calloc(sizeof(*mP), mNumChans); mP.reinit(mNumChans, true);
for (int i = 0; i < mNumChans; i++) for (int i = 0; i < mNumChans; i++)
{ {
@ -194,12 +194,7 @@ bool EffectReverb::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelName
bool EffectReverb::ProcessFinalize() bool EffectReverb::ProcessFinalize()
{ {
for (int i = 0; i < mNumChans; i++) mP.reset();
{
reverb_delete(&mP[i].reverb);
}
free(mP);
return true; return true;
} }

View File

@ -97,7 +97,7 @@ private:
private: private:
unsigned mNumChans {}; unsigned mNumChans {};
Reverb_priv_t *mP; ArrayOf<Reverb_priv_t> mP;
Params mParams; Params mParams;

View File

@ -29,16 +29,15 @@ using std::max;
#define FIFO_SIZE_T size_t #define FIFO_SIZE_T size_t
#define FIFO_MIN 0x4000 #define FIFO_MIN 0x4000
#define fifo_read_ptr(f) fifo_read(f, (FIFO_SIZE_T)0, NULL) #define fifo_read_ptr(f) fifo_read(f, (FIFO_SIZE_T)0, NULL)
#define lsx_zalloc(var, n) var = (float *)calloc(n, sizeof(*var)) #define lsx_zalloc(var, n) (var.reinit(n, true), var.get())
#define filter_advance(p) if (--(p)->ptr < (p)->buffer) (p)->ptr += (p)->size #define filter_advance(p) if (--(p)->ptr < (p)->buffer.get()) (p)->ptr += (p)->size
#define filter_delete(p) free((p)->buffer)
typedef struct { typedef struct {
char * data; ArrayOf<char> data;
size_t allocation; /* Number of bytes allocated for data. */ size_t allocation {}; /* Number of bytes allocated for data. */
size_t item_size; /* Size of each item in data */ size_t item_size {}; /* Size of each item in data */
size_t begin; /* Offset of the first byte to read. */ size_t begin {}; /* Offset of the first byte to read. */
size_t end; /* 1 + Offset of the last byte byte to read. */ size_t end {}; /* 1 + Offset of the last byte byte to read. */
} fifo_t; } fifo_t;
static void fifo_clear(fifo_t * f) static void fifo_clear(fifo_t * f)
@ -55,19 +54,19 @@ static void * fifo_reserve(fifo_t * f, FIFO_SIZE_T n)
while (1) { while (1) {
if (f->end + n <= f->allocation) { if (f->end + n <= f->allocation) {
void *p = f->data + f->end; void *p = f->data.get() + f->end;
f->end += n; f->end += n;
return p; return p;
} }
if (f->begin > FIFO_MIN) { if (f->begin > FIFO_MIN) {
memmove(f->data, f->data + f->begin, f->end - f->begin); memmove(f->data.get(), f->data.get() + f->begin, f->end - f->begin);
f->end -= f->begin; f->end -= f->begin;
f->begin = 0; f->begin = 0;
continue; continue;
} }
f->allocation += n; f->allocation += n;
f->data = (char *)realloc(f->data, f->allocation); f->data.reinit(f->allocation);
} }
} }
@ -81,7 +80,7 @@ static void * fifo_write(fifo_t * f, FIFO_SIZE_T n, void const * data)
static void * fifo_read(fifo_t * f, FIFO_SIZE_T n, void * data) static void * fifo_read(fifo_t * f, FIFO_SIZE_T n, void * data)
{ {
char * ret = f->data + f->begin; char * ret = f->data.get() + f->begin;
n *= f->item_size; n *= f->item_size;
if (n > (FIFO_SIZE_T)(f->end - f->begin)) if (n > (FIFO_SIZE_T)(f->end - f->begin))
return NULL; return NULL;
@ -91,22 +90,18 @@ static void * fifo_read(fifo_t * f, FIFO_SIZE_T n, void * data)
return ret; return ret;
} }
static void fifo_delete(fifo_t * f)
{
free(f->data);
}
static void fifo_create(fifo_t * f, FIFO_SIZE_T item_size) static void fifo_create(fifo_t * f, FIFO_SIZE_T item_size)
{ {
f->item_size = item_size; f->item_size = item_size;
f->allocation = FIFO_MIN; f->allocation = FIFO_MIN;
f->data = (char *)malloc(f->allocation); f->data.reinit(f->allocation);
fifo_clear(f); fifo_clear(f);
} }
typedef struct { typedef struct {
size_t size; size_t size;
float * buffer, * ptr; ArrayOf<float> buffer;
float * ptr;
float store; float store;
} filter_t; } filter_t;
@ -199,23 +194,13 @@ static void filter_array_process(filter_array_t * p,
} }
} }
static void filter_array_delete(filter_array_t * p)
{
size_t i;
for (i = 0; i < array_length(allpass_lengths); ++i)
filter_delete(&p->allpass[i]);
for (i = 0; i < array_length(comb_lengths); ++i)
filter_delete(&p->comb[i]);
}
typedef struct { typedef struct {
float feedback; float feedback {};
float hf_damping; float hf_damping {};
float gain; float gain {};
fifo_t input_fifo; fifo_t input_fifo {};
filter_array_t chan[2]; filter_array_t chan[2];
float * out[2]; ArrayOf<float> out[2];
} reverb_t; } reverb_t;
static void reverb_create(reverb_t * p, double sample_rate_Hz, static void reverb_create(reverb_t * p, double sample_rate_Hz,
@ -254,17 +239,7 @@ static void reverb_process(reverb_t * p, size_t length)
{ {
size_t i; size_t i;
for (i = 0; i < 2 && p->out[i]; ++i) for (i = 0; i < 2 && p->out[i]; ++i)
filter_array_process(p->chan + i, length, (float *) fifo_read_ptr(&p->input_fifo), p->out[i], &p->feedback, &p->hf_damping, &p->gain); filter_array_process(p->chan + i, length, (float *) fifo_read_ptr(&p->input_fifo), p->out[i].get(), &p->feedback, &p->hf_damping, &p->gain);
fifo_read(&p->input_fifo, length, NULL); fifo_read(&p->input_fifo, length, NULL);
} }
static void reverb_delete(reverb_t * p)
{
size_t i;
for (i = 0; i < 2 && p->out[i]; ++i) {
free(p->out[i]);
filter_array_delete(p->chan + i);
}
fifo_delete(&p->input_fifo);
}

View File

@ -33,38 +33,29 @@ public:
ResampleBuf() ResampleBuf()
{ {
processed = 0; processed = 0;
buf = NULL;
leftBuffer = NULL;
rightBuffer = NULL;
SBSMSBuf = NULL;
outputLeftTrack = NULL; outputLeftTrack = NULL;
outputRightTrack = NULL; outputRightTrack = NULL;
} }
~ResampleBuf() ~ResampleBuf()
{ {
if(buf) free(buf);
if(leftBuffer) free(leftBuffer);
if(rightBuffer) free(rightBuffer);
if(SBSMSBuf) free(SBSMSBuf);
} }
bool bPitch; bool bPitch;
audio *buf; ArrayOf<audio> buf;
double ratio; double ratio;
sampleCount processed; sampleCount processed;
size_t blockSize; size_t blockSize;
long SBSMSBlockSize; long SBSMSBlockSize;
sampleCount offset; sampleCount offset;
sampleCount end; sampleCount end;
float *leftBuffer; ArrayOf<float> leftBuffer;
float *rightBuffer; ArrayOf<float> rightBuffer;
WaveTrack *leftTrack; WaveTrack *leftTrack;
WaveTrack *rightTrack; WaveTrack *rightTrack;
std::unique_ptr<SBSMS> sbsms; std::unique_ptr<SBSMS> sbsms;
std::unique_ptr<SBSMSInterface> iface; std::unique_ptr<SBSMSInterface> iface;
audio *SBSMSBuf; ArrayOf<audio> SBSMSBuf;
// Not required by callbacks, but makes for easier cleanup // Not required by callbacks, but makes for easier cleanup
std::unique_ptr<Resampler> resampler; std::unique_ptr<Resampler> resampler;
@ -104,8 +95,8 @@ long resampleCB(void *cb_data, SBSMSFrame *data)
); );
// Get the samples from the tracks and put them in the buffers. // Get the samples from the tracks and put them in the buffers.
r->leftTrack->Get((samplePtr)(r->leftBuffer), floatSample, r->offset, blockSize); r->leftTrack->Get((samplePtr)(r->leftBuffer.get()), floatSample, r->offset, blockSize);
r->rightTrack->Get((samplePtr)(r->rightBuffer), floatSample, r->offset, blockSize); r->rightTrack->Get((samplePtr)(r->rightBuffer.get()), floatSample, r->offset, blockSize);
// convert to sbsms audio format // convert to sbsms audio format
for(decltype(blockSize) i=0; i<blockSize; i++) { for(decltype(blockSize) i=0; i<blockSize; i++) {
@ -113,7 +104,7 @@ long resampleCB(void *cb_data, SBSMSFrame *data)
r->buf[i][1] = r->rightBuffer[i]; r->buf[i][1] = r->rightBuffer[i];
} }
data->buf = r->buf; data->buf = r->buf.get();
data->size = blockSize; data->size = blockSize;
if(r->bPitch) { if(r->bPitch) {
float t0 = r->processed.as_float() / r->iface->getSamplesToInput(); float t0 = r->processed.as_float() / r->iface->getSamplesToInput();
@ -132,8 +123,8 @@ long resampleCB(void *cb_data, SBSMSFrame *data)
long postResampleCB(void *cb_data, SBSMSFrame *data) long postResampleCB(void *cb_data, SBSMSFrame *data)
{ {
ResampleBuf *r = (ResampleBuf*) cb_data; ResampleBuf *r = (ResampleBuf*) cb_data;
auto count = r->sbsms->read(r->iface.get(), r->SBSMSBuf, r->SBSMSBlockSize); auto count = r->sbsms->read(r->iface.get(), r->SBSMSBuf.get(), r->SBSMSBlockSize);
data->buf = r->SBSMSBuf; data->buf = r->SBSMSBuf.get();
data->size = count; data->size = count;
data->ratio0 = 1.0 / r->ratio; data->ratio0 = 1.0 / r->ratio;
data->ratio1 = 1.0 / r->ratio; data->ratio1 = 1.0 / r->ratio;
@ -285,11 +276,11 @@ bool EffectSBSMS::Process()
ResampleBuf rb; ResampleBuf rb;
auto maxBlockSize = leftTrack->GetMaxBlockSize(); auto maxBlockSize = leftTrack->GetMaxBlockSize();
rb.blockSize = maxBlockSize; rb.blockSize = maxBlockSize;
rb.buf = (audio*)calloc(rb.blockSize,sizeof(audio)); rb.buf.reinit(rb.blockSize, true);
rb.leftTrack = leftTrack; rb.leftTrack = leftTrack;
rb.rightTrack = rightTrack?rightTrack:leftTrack; rb.rightTrack = rightTrack?rightTrack:leftTrack;
rb.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float)); rb.leftBuffer.reinit(maxBlockSize, true);
rb.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float)); rb.rightBuffer.reinit(maxBlockSize, true);
// Samples in selection // Samples in selection
auto samplesIn = end - start; auto samplesIn = end - start;
@ -325,7 +316,7 @@ bool EffectSBSMS::Process()
rb.resampler = std::make_unique<Resampler>(resampleCB, &rb, srProcess==srTrack?SlideIdentity:SlideConstant); rb.resampler = std::make_unique<Resampler>(resampleCB, &rb, srProcess==srTrack?SlideIdentity:SlideConstant);
rb.sbsms = std::make_unique<SBSMS>(rightTrack ? 2 : 1, rb.quality.get(), true); rb.sbsms = std::make_unique<SBSMS>(rightTrack ? 2 : 1, rb.quality.get(), true);
rb.SBSMSBlockSize = rb.sbsms->getInputFrameSize(); rb.SBSMSBlockSize = rb.sbsms->getInputFrameSize();
rb.SBSMSBuf = (audio*)calloc(rb.SBSMSBlockSize,sizeof(audio)); rb.SBSMSBuf.reinit(static_cast<size_t>(rb.SBSMSBlockSize), true);
// Note: width of getMaxPresamples() is only long. Widen it // Note: width of getMaxPresamples() is only long. Widen it
decltype(start) processPresamples = rb.quality->getMaxPresamples(); decltype(start) processPresamples = rb.quality->getMaxPresamples();

View File

@ -277,7 +277,8 @@ void AUControl::CreateCocoa()
return; return;
} }
AudioUnitCocoaViewInfo *viewInfo = (AudioUnitCocoaViewInfo *) malloc(dataSize); ArrayOf<char> buffer{ dataSize };
auto viewInfo = (AudioUnitCocoaViewInfo *) buffer.get();
if (viewInfo == NULL) if (viewInfo == NULL)
{ {
return; return;
@ -331,8 +332,6 @@ void AUControl::CreateCocoa()
} }
} }
free(viewInfo);
if (!mView) if (!mView)
{ {
return; return;
@ -474,7 +473,8 @@ void AUControl::CreateCarbon()
return; return;
} }
AudioComponentDescription *compList = (AudioComponentDescription *) malloc(dataSize); ArrayOf<char> buffer{ dataSize };
auto compList = (AudioComponentDescription *) buffer.get();
if (compList == NULL) if (compList == NULL)
{ {
return; return;
@ -488,11 +488,7 @@ void AUControl::CreateCarbon()
compList, compList,
&dataSize); &dataSize);
if (result != noErr) if (result != noErr)
{
free(compList);
return; return;
}
// Get the component // Get the component
AudioComponent comp = AudioComponentFindNext(NULL, &compList[0]); AudioComponent comp = AudioComponentFindNext(NULL, &compList[0]);
@ -500,9 +496,6 @@ void AUControl::CreateCarbon()
// Try to create an instance // Try to create an instance
result = AudioComponentInstanceNew(comp, &mInstance); result = AudioComponentInstanceNew(comp, &mInstance);
// Done with the list
free(compList);
if (result != noErr) if (result != noErr)
{ {
return; return;

View File

@ -2187,7 +2187,8 @@ void AudioUnitEffect::GetChannelCounts()
return; return;
} }
AUChannelInfo *info = (AUChannelInfo *) malloc(dataSize); ArrayOf<char> buffer{ dataSize };
auto info = (AUChannelInfo *) buffer.get();
// Retrieve the channel info // Retrieve the channel info
result = AudioUnitGetProperty(mUnit, result = AudioUnitGetProperty(mUnit,
@ -2202,7 +2203,6 @@ void AudioUnitEffect::GetChannelCounts()
mAudioIns = 2; mAudioIns = 2;
mAudioOuts = 2; mAudioOuts = 2;
free(info);
return; return;
} }

View File

@ -316,11 +316,6 @@ LV2Effect::LV2Effect(const LilvPlugin *plug)
mDialog = NULL; mDialog = NULL;
mURIMap = NULL;
mNumURIMap = 0;
mOptions = NULL;
mNumOptions = 0;
mIdleFeature = NULL; mIdleFeature = NULL;
mOptionsInterface = NULL; mOptionsInterface = NULL;
@ -329,19 +324,6 @@ LV2Effect::LV2Effect(const LilvPlugin *plug)
LV2Effect::~LV2Effect() LV2Effect::~LV2Effect()
{ {
if (mURIMap)
{
for (int i = 0; i < mNumURIMap; i++)
{
free(mURIMap[i]);
}
free(mURIMap);
}
if (mOptions)
{
free(mOptions);
}
} }
// ============================================================================ // ============================================================================
@ -675,7 +657,7 @@ bool LV2Effect::SetHost(EffectHostInterface *host)
AddFeature(LV2_UI_PREFIX "makeResident", NULL); AddFeature(LV2_UI_PREFIX "makeResident", NULL);
AddFeature(LV2_UI__noUserResize, NULL); AddFeature(LV2_UI__noUserResize, NULL);
AddFeature(LV2_BUF_SIZE__boundedBlockLength, NULL); AddFeature(LV2_BUF_SIZE__boundedBlockLength, NULL);
AddFeature(LV2_OPTIONS__options, mOptions); AddFeature(LV2_OPTIONS__options, mOptions.data());
AddFeature(LV2_URI_MAP_URI, &mUriMapFeature); AddFeature(LV2_URI_MAP_URI, &mUriMapFeature);
AddFeature(LV2_URID__map, &mURIDMapFeature); AddFeature(LV2_URID__map, &mURIDMapFeature);
AddFeature(LV2_URID__unmap, &mURIDUnmapFeature); AddFeature(LV2_URID__unmap, &mURIDUnmapFeature);
@ -1302,10 +1284,9 @@ bool LV2Effect::SaveParameters(const wxString & group)
size_t LV2Effect::AddOption(const char *key, uint32_t size, const char *type, void *value) size_t LV2Effect::AddOption(const char *key, uint32_t size, const char *type, void *value)
{ {
int ndx = mNumOptions; int ndx = mOptions.size();
mNumOptions += 1; mOptions.resize(1 + mOptions.size());
mOptions = (LV2_Options_Option *) realloc(mOptions, mNumOptions * sizeof(LV2_Options_Option));
memset(&mOptions[ndx], 0, sizeof(mOptions[ndx])); memset(&mOptions[ndx], 0, sizeof(mOptions[ndx]));
if (key != NULL) if (key != NULL)
@ -1323,26 +1304,24 @@ size_t LV2Effect::AddOption(const char *key, uint32_t size, const char *type, vo
LV2_Feature *LV2Effect::AddFeature(const char *uri, void *data) LV2_Feature *LV2Effect::AddFeature(const char *uri, void *data)
{ {
mFeatures.resize(mFeatures.size() + 1); size_t ndx = mFeatures.size();
mFeatures.resize(1 + mFeatures.size());
auto &pFeature = mFeatures.back();
if (uri != NULL) if (uri != NULL)
{ {
pFeature = make_movable<LV2_Feature>(); mFeatures[ndx].reset( safenew LV2_Feature );
pFeature->URI = uri; mFeatures[ndx]->URI = uri;
pFeature->data = data; mFeatures[ndx]->data = data;
} }
mFeaturePtrs.push_back(pFeature.get()); return mFeatures[ndx].get();
return pFeature.get();
} }
LilvInstance *LV2Effect::InitInstance(float sampleRate) LilvInstance *LV2Effect::InitInstance(float sampleRate)
{ {
LilvInstance *handle = lilv_plugin_instantiate(mPlug, LilvInstance *handle = lilv_plugin_instantiate(
sampleRate, mPlug, sampleRate,
mFeaturePtrs.data()); reinterpret_cast<const LV2_Feature *const *>(mFeatures.data()));
if (!handle) if (!handle)
{ {
return NULL; return NULL;
@ -1478,7 +1457,7 @@ bool LV2Effect::BuildFancy()
lilv_node_as_uri(uiType), lilv_node_as_uri(uiType),
lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(ui))), lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(ui))),
lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(ui))), lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(ui))),
mFeaturePtrs.data()); reinterpret_cast<const LV2_Feature *const *>(mFeatures.data()));
lilv_uis_free(uis); lilv_uis_free(uis);
@ -2033,19 +2012,19 @@ LV2_URID LV2Effect::urid_map(LV2_URID_Map_Handle handle, const char *uri)
LV2_URID LV2Effect::URID_Map(const char *uri) LV2_URID LV2Effect::URID_Map(const char *uri)
{ {
for (int i = 0; i < mNumURIMap; i++) size_t ndx = mURIMap.size();
for (int i = 0; i < ndx; i++)
{ {
if (strcmp(mURIMap[i], uri) == 0) if (strcmp(mURIMap[i].get(), uri) == 0)
{ {
return i + 1; return i + 1;
} }
} }
mNumURIMap += 1; mURIMap.resize(1 + mURIMap.size());
mURIMap = (char **) realloc(mURIMap, mNumURIMap * sizeof(char*)); mURIMap[ndx].reset( strdup(uri) );
mURIMap[mNumURIMap - 1] = strdup(uri);
return mNumURIMap; return ndx + 1;
} }
// static callback // static callback
@ -2056,9 +2035,9 @@ const char *LV2Effect::urid_unmap(LV2_URID_Unmap_Handle handle, LV2_URID urid)
const char *LV2Effect::URID_Unmap(LV2_URID urid) const char *LV2Effect::URID_Unmap(LV2_URID urid)
{ {
if (urid > 0 && urid <= (LV2_URID) mNumURIMap) if (urid > 0 && urid <= (LV2_URID) mURIMap.size())
{ {
return mURIMap[urid - 1]; return mURIMap[urid - 1].get();
} }
return NULL; return NULL;

View File

@ -15,7 +15,6 @@
#include "../../MemoryX.h" #include "../../MemoryX.h"
#include <vector> #include <vector>
#include <wx/checkbox.h> #include <wx/checkbox.h>
#include <wx/dialog.h> #include <wx/dialog.h>
#include <wx/dynarray.h> #include <wx/dynarray.h>
@ -289,8 +288,7 @@ private:
bool mUseGUI; bool mUseGUI;
char **mURIMap; std::vector< movable_ptr_with_deleter<char, freer> > mURIMap;
int mNumURIMap;
LV2_URI_Map_Feature mUriMapFeature; LV2_URI_Map_Feature mUriMapFeature;
LV2_URID_Map mURIDMapFeature; LV2_URID_Map mURIDMapFeature;
@ -302,11 +300,9 @@ private:
size_t mSampleRateOption; size_t mSampleRateOption;
LV2_Options_Interface *mOptionsInterface; LV2_Options_Interface *mOptionsInterface;
LV2_Options_Option *mOptions; std::vector<LV2_Options_Option> mOptions;
int mNumOptions;
std::vector<movable_ptr<LV2_Feature>> mFeatures; std::vector<movable_ptr<LV2_Feature>> mFeatures;
std::vector<LV2_Feature*> mFeaturePtrs;
LV2_Feature *mInstanceAccessFeature; LV2_Feature *mInstanceAccessFeature;
LV2_Feature *mParentFeature; LV2_Feature *mParentFeature;

View File

@ -240,7 +240,7 @@ wxWindow *ExportPlugin::OptionsCreate(wxWindow *parent, int WXUNUSED(format))
std::unique_ptr<Mixer> ExportPlugin::CreateMixer(const WaveTrackConstArray &inputTracks, std::unique_ptr<Mixer> ExportPlugin::CreateMixer(const WaveTrackConstArray &inputTracks,
const TimeTrack *timeTrack, const TimeTrack *timeTrack,
double startTime, double stopTime, double startTime, double stopTime,
unsigned numOutChannels, int outBufferSize, bool outInterleaved, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
double outRate, sampleFormat outFormat, double outRate, sampleFormat outFormat,
bool highQuality, MixerSpec *mixerSpec) bool highQuality, MixerSpec *mixerSpec)
{ {

View File

@ -123,7 +123,7 @@ protected:
std::unique_ptr<Mixer> CreateMixer(const WaveTrackConstArray &inputTracks, std::unique_ptr<Mixer> CreateMixer(const WaveTrackConstArray &inputTracks,
const TimeTrack *timeTrack, const TimeTrack *timeTrack,
double startTime, double stopTime, double startTime, double stopTime,
unsigned numOutChannels, int outBufferSize, bool outInterleaved, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
double outRate, sampleFormat outFormat, double outRate, sampleFormat outFormat,
bool highQuality = true, MixerSpec *mixerSpec = NULL); bool highQuality = true, MixerSpec *mixerSpec = NULL);

View File

@ -857,7 +857,7 @@ ProgressResult ExportFFmpeg::Export(AudacityProject *project,
if (!ret) if (!ret)
return ProgressResult::Cancelled; return ProgressResult::Cancelled;
int pcmBufferSize = 1024; size_t pcmBufferSize = 1024;
const WaveTrackConstArray waveTracks = const WaveTrackConstArray waveTracks =
tracks->GetWaveTrackConstArray(selectionOnly, false); tracks->GetWaveTrackConstArray(selectionOnly, false);
auto mixer = CreateMixer(waveTracks, auto mixer = CreateMixer(waveTracks,

View File

@ -173,6 +173,14 @@ static struct
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
struct FLAC__StreamMetadataDeleter {
void operator () (FLAC__StreamMetadata *p) const
{ if (p) ::FLAC__metadata_object_delete(p); }
};
using FLAC__StreamMetadataHandle = std::unique_ptr<
FLAC__StreamMetadata, FLAC__StreamMetadataDeleter
>;
class ExportFLAC final : public ExportPlugin class ExportFLAC final : public ExportPlugin
{ {
public: public:
@ -196,7 +204,7 @@ private:
bool GetMetadata(AudacityProject *project, const Tags *tags); bool GetMetadata(AudacityProject *project, const Tags *tags);
FLAC__StreamMetadata *mMetadata; FLAC__StreamMetadataHandle mMetadata;
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -248,7 +256,10 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
} }
if (mMetadata) { if (mMetadata) {
encoder.set_metadata(&mMetadata, 1); // set_metadata expects an array of pointers to metadata and a size.
// The size is 1.
FLAC__StreamMetadata *p = mMetadata.get();
encoder.set_metadata(&p, 1);
} }
sampleFormat format; sampleFormat format;
@ -299,9 +310,7 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
} }
#endif #endif
if (mMetadata) { mMetadata.reset();
::FLAC__metadata_object_delete(mMetadata);
}
const WaveTrackConstArray waveTracks = const WaveTrackConstArray waveTracks =
tracks->GetWaveTrackConstArray(selectionOnly, false); tracks->GetWaveTrackConstArray(selectionOnly, false);
@ -367,7 +376,7 @@ bool ExportFLAC::GetMetadata(AudacityProject *project, const Tags *tags)
if (tags == NULL) if (tags == NULL)
tags = project->GetTags(); tags = project->GetTags();
mMetadata = ::FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT); mMetadata.reset(::FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT));
wxString n; wxString n;
for (const auto &pair : tags->GetRange()) { for (const auto &pair : tags->GetRange()) {
@ -378,7 +387,7 @@ bool ExportFLAC::GetMetadata(AudacityProject *project, const Tags *tags)
} }
FLAC::Metadata::VorbisComment::Entry entry(n.mb_str(wxConvUTF8), FLAC::Metadata::VorbisComment::Entry entry(n.mb_str(wxConvUTF8),
v.mb_str(wxConvUTF8)); v.mb_str(wxConvUTF8));
::FLAC__metadata_object_vorbiscomment_append_comment(mMetadata, ::FLAC__metadata_object_vorbiscomment_append_comment(mMetadata.get(),
entry.get_entry(), entry.get_entry(),
true); true);
} }

View File

@ -185,7 +185,7 @@ public:
private: private:
int AddTags(AudacityProject *project, char **buffer, bool *endOfFile, const Tags *tags); int AddTags(AudacityProject *project, ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags);
#ifdef USE_LIBID3TAG #ifdef USE_LIBID3TAG
void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name); void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name);
#endif #endif
@ -242,15 +242,15 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
return ProgressResult::Cancelled; return ProgressResult::Cancelled;
} }
char *id3buffer = NULL; ArrayOf<char> id3buffer;
int id3len; int id3len;
bool endOfFile; bool endOfFile;
id3len = AddTags(project, &id3buffer, &endOfFile, metadata); id3len = AddTags(project, id3buffer, &endOfFile, metadata);
if (id3len && !endOfFile) if (id3len && !endOfFile)
outFile.Write(id3buffer, id3len); outFile.Write(id3buffer.get(), id3len);
// Values taken from the twolame simple encoder sample // Values taken from the twolame simple encoder sample
const int pcmBufferSize = 9216 / 2; // number of samples const size_t pcmBufferSize = 9216 / 2; // number of samples
const size_t mp2BufferSize = 16384u; // bytes const size_t mp2BufferSize = 16384u; // bytes
// We allocate a buffer which is twice as big as the // We allocate a buffer which is twice as big as the
@ -307,11 +307,7 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
/* Write ID3 tag if it was supposed to be at the end of the file */ /* Write ID3 tag if it was supposed to be at the end of the file */
if (id3len && endOfFile) if (id3len && endOfFile)
outFile.Write(id3buffer, id3len); outFile.Write(id3buffer.get(), id3len);
if (id3buffer) {
free(id3buffer);
}
/* Close file */ /* Close file */
@ -326,11 +322,16 @@ wxWindow *ExportMP2::OptionsCreate(wxWindow *parent, int format)
return safenew ExportMP2Options(parent, format); return safenew ExportMP2Options(parent, format);
} }
struct id3_tag_deleter {
void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
};
using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
// returns buffer len; caller frees // returns buffer len; caller frees
int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool *endOfFile, const Tags *tags) int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags)
{ {
#ifdef USE_LIBID3TAG #ifdef USE_LIBID3TAG
struct id3_tag *tp = id3_tag_new(); id3_tag_holder tp { id3_tag_new() };
for (const auto &pair : tags->GetRange()) { for (const auto &pair : tags->GetRange()) {
const auto &n = pair.first; const auto &n = pair.first;
@ -349,7 +350,7 @@ int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool
else if (n.CmpNoCase(TAG_YEAR) == 0) { else if (n.CmpNoCase(TAG_YEAR) == 0) {
// LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR), // LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
// so we add old one as well. // so we add old one as well.
AddFrame(tp, n, v, "TYER"); AddFrame(tp.get(), n, v, "TYER");
name = ID3_FRAME_YEAR; name = ID3_FRAME_YEAR;
} }
else if (n.CmpNoCase(TAG_GENRE) == 0) { else if (n.CmpNoCase(TAG_GENRE) == 0) {
@ -362,7 +363,7 @@ int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool
name = ID3_FRAME_TRACK; name = ID3_FRAME_TRACK;
} }
AddFrame(tp, n, v, name); AddFrame(tp.get(), n, v, name);
} }
tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression
@ -378,11 +379,10 @@ int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool
id3_length_t len; id3_length_t len;
len = id3_tag_render(tp, 0); len = id3_tag_render(tp.get(), 0);
*buffer = (char *)malloc(len); buffer.reinit(len);
len = id3_tag_render(tp, (id3_byte_t *)*buffer); len = id3_tag_render(tp.get(), (id3_byte_t *)buffer.get());
id3_tag_delete(tp);
return len; return len;
#else //ifdef USE_LIBID3TAG #else //ifdef USE_LIBID3TAG
@ -402,8 +402,8 @@ void ExportMP2::AddFrame(struct id3_tag *tp, const wxString & n, const wxString
id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1); id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
} }
id3_ucs4_t *ucs4 = MallocString<id3_ucs4_t> ucs4 {
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)); id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
if (strcmp(name, ID3_FRAME_COMMENT) == 0) { if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
// A hack to get around iTunes not recognizing the comment. The // A hack to get around iTunes not recognizing the comment. The
@ -413,22 +413,20 @@ void ExportMP2::AddFrame(struct id3_tag *tp, const wxString & n, const wxString
// way of clearing the field, so do it directly. // way of clearing the field, so do it directly.
id3_field *f = id3_frame_field(frame, 1); id3_field *f = id3_frame_field(frame, 1);
memset(f->immediate.value, 0, sizeof(f->immediate.value)); memset(f->immediate.value, 0, sizeof(f->immediate.value));
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4); id3_field_setfullstring(id3_frame_field(frame, 3), ucs4.get());
} }
else if (strcmp(name, "TXXX") == 0) { else if (strcmp(name, "TXXX") == 0) {
id3_field_setstring(id3_frame_field(frame, 2), ucs4); id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
free(ucs4);
ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)); ucs4.reset(id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)));
id3_field_setstring(id3_frame_field(frame, 1), ucs4); id3_field_setstring(id3_frame_field(frame, 1), ucs4.get());
} }
else { else {
id3_field_setstrings(id3_frame_field(frame, 1), 1, &ucs4); auto addr = ucs4.get();
id3_field_setstrings(id3_frame_field(frame, 1), 1, &addr);
} }
free(ucs4);
id3_tag_attachframe(tp, frame); id3_tag_attachframe(tp, frame);
} }
#endif #endif

View File

@ -1617,7 +1617,7 @@ private:
int FindValue(CHOICES *choices, int cnt, int needle, int def); int FindValue(CHOICES *choices, int cnt, int needle, int def);
wxString FindName(CHOICES *choices, int cnt, int needle); wxString FindName(CHOICES *choices, int cnt, int needle);
int AskResample(int bitrate, int rate, int lowrate, int highrate); int AskResample(int bitrate, int rate, int lowrate, int highrate);
int AddTags(AudacityProject *project, char **buffer, bool *endOfFile, const Tags *tags); int AddTags(AudacityProject *project, ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags);
#ifdef USE_LIBID3TAG #ifdef USE_LIBID3TAG
void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name); void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name);
#endif #endif
@ -1796,12 +1796,12 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
return ProgressResult::Cancelled; return ProgressResult::Cancelled;
} }
char *id3buffer = NULL; ArrayOf<char> id3buffer;
int id3len; int id3len;
bool endOfFile; bool endOfFile;
id3len = AddTags(project, &id3buffer, &endOfFile, metadata); id3len = AddTags(project, id3buffer, &endOfFile, metadata);
if (id3len && !endOfFile) { if (id3len && !endOfFile) {
outFile.Write(id3buffer, id3len); outFile.Write(id3buffer.get(), id3len);
} }
wxFileOffset pos = outFile.Tell(); wxFileOffset pos = outFile.Tell();
@ -1890,11 +1890,7 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
// Write ID3 tag if it was supposed to be at the end of the file // Write ID3 tag if it was supposed to be at the end of the file
if (id3len && endOfFile) { if (id3len && endOfFile) {
outFile.Write(id3buffer, id3len); outFile.Write(id3buffer.get(), id3len);
}
if (id3buffer) {
free(id3buffer);
} }
// Always write the info (Xing/Lame) tag. Until we stop supporting Lame // Always write the info (Xing/Lame) tag. Until we stop supporting Lame
@ -2008,11 +2004,16 @@ int ExportMP3::AskResample(int bitrate, int rate, int lowrate, int highrate)
return wxAtoi(choice->GetStringSelection()); return wxAtoi(choice->GetStringSelection());
} }
struct id3_tag_deleter {
void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
};
using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
// returns buffer len; caller frees // returns buffer len; caller frees
int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *endOfFile, const Tags *tags) int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), ArrayOf<char> &buffer, bool *endOfFile, const Tags *tags)
{ {
#ifdef USE_LIBID3TAG #ifdef USE_LIBID3TAG
struct id3_tag *tp = id3_tag_new(); id3_tag_holder tp { id3_tag_new() };
for (const auto &pair : tags->GetRange()) { for (const auto &pair : tags->GetRange()) {
const auto &n = pair.first; const auto &n = pair.first;
@ -2031,7 +2032,7 @@ int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *
else if (n.CmpNoCase(TAG_YEAR) == 0) { else if (n.CmpNoCase(TAG_YEAR) == 0) {
// LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR), // LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
// so we add old one as well. // so we add old one as well.
AddFrame(tp, n, v, "TYER"); AddFrame(tp.get(), n, v, "TYER");
name = ID3_FRAME_YEAR; name = ID3_FRAME_YEAR;
} }
else if (n.CmpNoCase(TAG_GENRE) == 0) { else if (n.CmpNoCase(TAG_GENRE) == 0) {
@ -2044,7 +2045,7 @@ int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *
name = ID3_FRAME_TRACK; name = ID3_FRAME_TRACK;
} }
AddFrame(tp, n, v, name); AddFrame(tp.get(), n, v, name);
} }
tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression
@ -2060,11 +2061,9 @@ int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *
id3_length_t len; id3_length_t len;
len = id3_tag_render(tp, 0); len = id3_tag_render(tp.get(), 0);
*buffer = (char *)malloc(len); buffer.reinit(len);
len = id3_tag_render(tp, (id3_byte_t *)*buffer); len = id3_tag_render(tp.get(), (id3_byte_t *)buffer.get());
id3_tag_delete(tp);
return len; return len;
#else //ifdef USE_LIBID3TAG #else //ifdef USE_LIBID3TAG
@ -2084,8 +2083,8 @@ void ExportMP3::AddFrame(struct id3_tag *tp, const wxString & n, const wxString
id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1); id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
} }
id3_ucs4_t *ucs4 = MallocString<id3_ucs4_t> ucs4{
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)); id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
if (strcmp(name, ID3_FRAME_COMMENT) == 0) { if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
// A hack to get around iTunes not recognizing the comment. The // A hack to get around iTunes not recognizing the comment. The
@ -2094,27 +2093,25 @@ void ExportMP3::AddFrame(struct id3_tag *tp, const wxString & n, const wxString
// (which one???) or just clear it. Unfortunately, there's no supported // (which one???) or just clear it. Unfortunately, there's no supported
// way of clearing the field, so do it directly. // way of clearing the field, so do it directly.
struct id3_frame *frame2 = id3_frame_new(name); struct id3_frame *frame2 = id3_frame_new(name);
id3_field_setfullstring(id3_frame_field(frame2, 3), ucs4); id3_field_setfullstring(id3_frame_field(frame2, 3), ucs4.get());
id3_field *f2 = id3_frame_field(frame2, 1); id3_field *f2 = id3_frame_field(frame2, 1);
memset(f2->immediate.value, 0, sizeof(f2->immediate.value)); memset(f2->immediate.value, 0, sizeof(f2->immediate.value));
id3_tag_attachframe(tp, frame2); id3_tag_attachframe(tp, frame2);
// Now install a second frame with the standard default language = "XXX" // Now install a second frame with the standard default language = "XXX"
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4); id3_field_setfullstring(id3_frame_field(frame, 3), ucs4.get());
} }
else if (strcmp(name, "TXXX") == 0) { else if (strcmp(name, "TXXX") == 0) {
id3_field_setstring(id3_frame_field(frame, 2), ucs4); id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
free(ucs4);
ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)); ucs4.reset(id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)));
id3_field_setstring(id3_frame_field(frame, 1), ucs4); id3_field_setstring(id3_frame_field(frame, 1), ucs4.get());
} }
else { else {
id3_field_setstrings(id3_frame_field(frame, 1), 1, &ucs4); auto addr = ucs4.get();
id3_field_setstrings(id3_frame_field(frame, 1), 1, &addr);
} }
free(ucs4);
id3_tag_attachframe(tp, frame); id3_tag_attachframe(tp, frame);
} }
#endif #endif

View File

@ -121,7 +121,7 @@ bool ExportOGGOptions::TransferDataFromWindow()
// ExportOGG // ExportOGG
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#define SAMPLES_PER_RUN 8192 #define SAMPLES_PER_RUN 8192u
class ExportOGG final : public ExportPlugin class ExportOGG final : public ExportPlugin
{ {

View File

@ -28,6 +28,7 @@
#include "../FileFormats.h" #include "../FileFormats.h"
#include "../Internat.h" #include "../Internat.h"
#include "../MemoryX.h"
#include "../Mix.h" #include "../Mix.h"
#include "../Prefs.h" #include "../Prefs.h"
#include "../Project.h" #include "../Project.h"
@ -328,7 +329,7 @@ public:
private: private:
char *AdjustString(const wxString & wxStr, int sf_format); ArrayOf<char> AdjustString(const wxString & wxStr, int sf_format);
bool AddStrings(AudacityProject *project, SNDFILE *sf, const Tags *tags, int sf_format); bool AddStrings(AudacityProject *project, SNDFILE *sf, const Tags *tags, int sf_format);
void AddID3Chunk(wxString fName, const Tags *tags, int sf_format); void AddID3Chunk(wxString fName, const Tags *tags, int sf_format);
@ -472,7 +473,7 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
else else
format = int16Sample; format = int16Sample;
int maxBlockLen = 44100 * 5; size_t maxBlockLen = 44100 * 5;
const WaveTrackConstArray waveTracks = const WaveTrackConstArray waveTracks =
tracks->GetWaveTrackConstArray(selectionOnly, false); tracks->GetWaveTrackConstArray(selectionOnly, false);
@ -538,7 +539,7 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
return updateResult; return updateResult;
} }
char *ExportPCM::AdjustString(const wxString & wxStr, int sf_format) ArrayOf<char> ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
{ {
bool b_aiff = false; bool b_aiff = false;
if ((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF) if ((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF)
@ -547,34 +548,26 @@ char *ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
// We must convert the string to 7 bit ASCII // We must convert the string to 7 bit ASCII
size_t sz = wxStr.length(); size_t sz = wxStr.length();
if(sz == 0) if(sz == 0)
return NULL; return {};
// Size for secure malloc in case of local wide char usage // Size for secure allocation in case of local wide char usage
size_t sr = (sz+4) * 2; size_t sr = (sz+4) * 2;
char *pDest = (char *)malloc(sr); ArrayOf<char> pDest{ sr, true };
if (!pDest) if (!pDest)
return NULL; return {};
char *pSrc = (char *)malloc(sr); ArrayOf<char> pSrc{ sr, true };
if (!pSrc) if (!pSrc)
{ return {};
free(pDest);
return NULL;
}
memset(pDest, 0, sr);
memset(pSrc, 0, sr);
if(wxStr.mb_str(wxConvISO8859_1)) if(wxStr.mb_str(wxConvISO8859_1))
strncpy(pSrc, wxStr.mb_str(wxConvISO8859_1), sz); strncpy(pSrc.get(), wxStr.mb_str(wxConvISO8859_1), sz);
else if(wxStr.mb_str()) else if(wxStr.mb_str())
strncpy(pSrc, wxStr.mb_str(), sz); strncpy(pSrc.get(), wxStr.mb_str(), sz);
else { else
free(pDest); return {};
free(pSrc);
return NULL;
}
char *pD = pDest; char *pD = pDest.get();
char *pS = pSrc; char *pS = pSrc.get();
unsigned char c; unsigned char c;
// ISO Latin to 7 bit ascii conversion table (best approximation) // ISO Latin to 7 bit ascii conversion table (best approximation)
@ -622,13 +615,11 @@ char *ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
} }
*pD = '\0'; *pD = '\0';
free(pSrc);
if(b_aiff) { if(b_aiff) {
int len = (int)strlen(pDest); int len = (int)strlen(pDest.get());
if((len % 2) != 0) { if((len % 2) != 0) {
// In case of an odd length string, add a space char // In case of an odd length string, add a space char
strcat(pDest, " "); strcat(pDest.get(), " ");
} }
} }
@ -638,84 +629,80 @@ char *ExportPCM::AdjustString(const wxString & wxStr, int sf_format)
bool ExportPCM::AddStrings(AudacityProject * WXUNUSED(project), SNDFILE *sf, const Tags *tags, int sf_format) bool ExportPCM::AddStrings(AudacityProject * WXUNUSED(project), SNDFILE *sf, const Tags *tags, int sf_format)
{ {
if (tags->HasTag(TAG_TITLE)) { if (tags->HasTag(TAG_TITLE)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_TITLE), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_TITLE), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_TITLE, ascii7Str); sf_set_string(sf, SF_STR_TITLE, ascii7Str.get());
free(ascii7Str);
} }
} }
if (tags->HasTag(TAG_ALBUM)) { if (tags->HasTag(TAG_ALBUM)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_ALBUM), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_ALBUM), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_ALBUM, ascii7Str); sf_set_string(sf, SF_STR_ALBUM, ascii7Str.get());
free(ascii7Str);
} }
} }
if (tags->HasTag(TAG_ARTIST)) { if (tags->HasTag(TAG_ARTIST)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_ARTIST), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_ARTIST), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_ARTIST, ascii7Str); sf_set_string(sf, SF_STR_ARTIST, ascii7Str.get());
free(ascii7Str);
} }
} }
if (tags->HasTag(TAG_COMMENTS)) { if (tags->HasTag(TAG_COMMENTS)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_COMMENTS), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_COMMENTS), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_COMMENT, ascii7Str); sf_set_string(sf, SF_STR_COMMENT, ascii7Str.get());
free(ascii7Str);
} }
} }
if (tags->HasTag(TAG_YEAR)) { if (tags->HasTag(TAG_YEAR)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_YEAR), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_YEAR), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_DATE, ascii7Str); sf_set_string(sf, SF_STR_DATE, ascii7Str.get());
free(ascii7Str);
} }
} }
if (tags->HasTag(TAG_GENRE)) { if (tags->HasTag(TAG_GENRE)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_GENRE), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_GENRE), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_GENRE, ascii7Str); sf_set_string(sf, SF_STR_GENRE, ascii7Str.get());
free(ascii7Str);
} }
} }
if (tags->HasTag(TAG_COPYRIGHT)) { if (tags->HasTag(TAG_COPYRIGHT)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_COPYRIGHT), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_COPYRIGHT), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_COPYRIGHT, ascii7Str); sf_set_string(sf, SF_STR_COPYRIGHT, ascii7Str.get());
free(ascii7Str);
} }
} }
if (tags->HasTag(TAG_SOFTWARE)) { if (tags->HasTag(TAG_SOFTWARE)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_SOFTWARE), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_SOFTWARE), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_SOFTWARE, ascii7Str); sf_set_string(sf, SF_STR_SOFTWARE, ascii7Str.get());
free(ascii7Str);
} }
} }
if (tags->HasTag(TAG_TRACK)) { if (tags->HasTag(TAG_TRACK)) {
char * ascii7Str = AdjustString(tags->GetTag(TAG_TRACK), sf_format); auto ascii7Str = AdjustString(tags->GetTag(TAG_TRACK), sf_format);
if (ascii7Str) { if (ascii7Str) {
sf_set_string(sf, SF_STR_TRACKNUMBER, ascii7Str); sf_set_string(sf, SF_STR_TRACKNUMBER, ascii7Str.get());
free(ascii7Str);
} }
} }
return true; return true;
} }
struct id3_tag_deleter {
void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
};
using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format) void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
{ {
#ifdef USE_LIBID3TAG #ifdef USE_LIBID3TAG
struct id3_tag *tp = id3_tag_new(); id3_tag_holder tp { id3_tag_new() };
for (const auto &pair : tags->GetRange()) { for (const auto &pair : tags->GetRange()) {
const auto &n = pair.first; const auto &n = pair.first;
@ -756,8 +743,8 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1); id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
} }
id3_ucs4_t *ucs4 = MallocString<id3_ucs4_t> ucs4{
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)); id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
if (strcmp(name, ID3_FRAME_COMMENT) == 0) { if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
// A hack to get around iTunes not recognizing the comment. The // A hack to get around iTunes not recognizing the comment. The
@ -767,23 +754,21 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
// way of clearing the field, so do it directly. // way of clearing the field, so do it directly.
id3_field *f = id3_frame_field(frame, 1); id3_field *f = id3_frame_field(frame, 1);
memset(f->immediate.value, 0, sizeof(f->immediate.value)); memset(f->immediate.value, 0, sizeof(f->immediate.value));
id3_field_setfullstring(id3_frame_field(frame, 3), ucs4); id3_field_setfullstring(id3_frame_field(frame, 3), ucs4.get());
} }
else if (strcmp(name, "TXXX") == 0) { else if (strcmp(name, "TXXX") == 0) {
id3_field_setstring(id3_frame_field(frame, 2), ucs4); id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
free(ucs4);
ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)); ucs4.reset(id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) n.mb_str(wxConvUTF8)));
id3_field_setstring(id3_frame_field(frame, 1), ucs4); id3_field_setstring(id3_frame_field(frame, 1), ucs4.get());
} }
else { else {
id3_field_setstrings(id3_frame_field(frame, 1), 1, &ucs4); auto addr = ucs4.get();
id3_field_setstrings(id3_frame_field(frame, 1), 1, &addr);
} }
free(ucs4); id3_tag_attachframe(tp.get(), frame);
id3_tag_attachframe(tp, frame);
} }
tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression
@ -797,24 +782,19 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
id3_length_t len; id3_length_t len;
len = id3_tag_render(tp, 0); len = id3_tag_render(tp.get(), 0);
if (len == 0) { if (len == 0)
id3_tag_delete(tp);
return; return;
}
if ((len % 2) != 0) len++; // Length must be even. if ((len % 2) != 0) len++; // Length must be even.
id3_byte_t *buffer = (id3_byte_t *)malloc(len); ArrayOf<id3_byte_t> buffer { len, true };
if (buffer == NULL) { if (buffer == NULL)
id3_tag_delete(tp);
return; return;
}
// Zero all locations, for ending odd UTF16 content // Zero all locations, for ending odd UTF16 content
// correctly, i.e., two '\0's at the end. // correctly, i.e., two '\0's at the end.
memset(buffer, 0, len);
id3_tag_render(tp, buffer); id3_tag_render(tp.get(), buffer.get());
id3_tag_delete(tp);
wxFFile f(fName, wxT("r+b")); wxFFile f(fName, wxT("r+b"));
// FIXME: TRAP_ERR wxFFILE ops in Export PCM ID3 could fail. // FIXME: TRAP_ERR wxFFILE ops in Export PCM ID3 could fail.
@ -831,7 +811,7 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
} }
f.Write(&sz, 4); f.Write(&sz, 4);
f.Write(buffer, len); f.Write(buffer.get(), len);
sz = (wxUint32) f.Tell() - 8; sz = (wxUint32) f.Tell() - 8;
if ((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF) if ((sf_format & SF_FORMAT_TYPEMASK) == SF_FORMAT_AIFF)
@ -842,8 +822,6 @@ void ExportPCM::AddID3Chunk(wxString fName, const Tags *tags, int sf_format)
f.Close(); f.Close();
} }
free(buffer);
#endif #endif
return; return;
} }

View File

@ -732,13 +732,10 @@ ProgressResult FFmpegImportFileHandle::WriteData(streamContext *sc)
} }
// Allocate the buffer to store audio. // Allocate the buffer to store audio.
int insamples = sc->m_decodedAudioSamplesValidSiz / sc->m_samplesize; auto insamples = sc->m_decodedAudioSamplesValidSiz / sc->m_samplesize;
int nChannels = sc->m_stream->codec->channels < sc->m_initialchannels ? sc->m_stream->codec->channels : sc->m_initialchannels; size_t nChannels = std::min(sc->m_stream->codec->channels, sc->m_initialchannels);
uint8_t **tmp = (uint8_t **) malloc(sizeof(uint8_t *) * nChannels);
for (int chn = 0; chn < nChannels; chn++) ArraysOf<uint8_t> tmp{ nChannels, sc->m_osamplesize * (insamples / nChannels) };
{
tmp[chn] = (uint8_t *) malloc(sc->m_osamplesize * (insamples / nChannels));
}
// Separate the channels and convert input sample format to 16-bit // Separate the channels and convert input sample format to 16-bit
uint8_t *in = sc->m_decodedAudioSamples.get(); uint8_t *in = sc->m_decodedAudioSamples.get();
@ -754,36 +751,31 @@ ProgressResult FFmpegImportFileHandle::WriteData(streamContext *sc)
{ {
case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_U8:
case AV_SAMPLE_FMT_U8P: case AV_SAMPLE_FMT_U8P:
((int16_t *)tmp[chn])[index] = (int16_t) (*(uint8_t *)in - 0x80) << 8; ((int16_t *)tmp[chn].get())[index] = (int16_t) (*(uint8_t *)in - 0x80) << 8;
break; break;
case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16:
case AV_SAMPLE_FMT_S16P: case AV_SAMPLE_FMT_S16P:
((int16_t *)tmp[chn])[index] = (int16_t) *(int16_t *)in; ((int16_t *)tmp[chn].get())[index] = (int16_t) *(int16_t *)in;
break; break;
case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32:
case AV_SAMPLE_FMT_S32P: case AV_SAMPLE_FMT_S32P:
((float *)tmp[chn])[index] = (float) *(int32_t *)in * (1.0 / (1u << 31)); ((float *)tmp[chn].get())[index] = (float) *(int32_t *)in * (1.0 / (1u << 31));
break; break;
case AV_SAMPLE_FMT_FLT: case AV_SAMPLE_FMT_FLT:
case AV_SAMPLE_FMT_FLTP: case AV_SAMPLE_FMT_FLTP:
((float *)tmp[chn])[index] = (float) *(float *)in; ((float *)tmp[chn].get())[index] = (float) *(float *)in;
break; break;
case AV_SAMPLE_FMT_DBL: case AV_SAMPLE_FMT_DBL:
case AV_SAMPLE_FMT_DBLP: case AV_SAMPLE_FMT_DBLP:
((float *)tmp[chn])[index] = (float) *(double *)in; ((float *)tmp[chn].get())[index] = (float) *(double *)in;
break; break;
default: default:
wxLogError(wxT("Stream %d has unrecognized sample format %d."), streamid, sc->m_samplefmt); wxLogError(wxT("Stream %d has unrecognized sample format %d."), streamid, sc->m_samplefmt);
for (int chn=0; chn < nChannels; chn++)
{
free(tmp[chn]);
}
free(tmp);
return ProgressResult::Success; return ProgressResult::Success;
break; break;
} }
@ -798,12 +790,9 @@ ProgressResult FFmpegImportFileHandle::WriteData(streamContext *sc)
auto iter2 = iter->begin(); auto iter2 = iter->begin();
for (int chn=0; chn < nChannels; ++iter2, ++chn) for (int chn=0; chn < nChannels; ++iter2, ++chn)
{ {
iter2->get()->Append((samplePtr)tmp[chn],sc->m_osamplefmt,index); iter2->get()->Append((samplePtr)tmp[chn].get(), sc->m_osamplefmt, index);
free(tmp[chn]);
} }
free(tmp);
// Try to update the progress indicator (and see if user wants to cancel) // Try to update the progress indicator (and see if user wants to cancel)
auto updateResult = ProgressResult::Success; auto updateResult = ProgressResult::Success;
int64_t filesize = avio_size(mFormatContext->pb); int64_t filesize = avio_size(mFormatContext->pb);

View File

@ -356,9 +356,8 @@ void MP3ImportFileHandle::ImportID3(Tags *tags)
else if (frame->nfields == 3) { else if (frame->nfields == 3) {
ustr = id3_field_getstring(&frame->fields[1]); ustr = id3_field_getstring(&frame->fields[1]);
if (ustr) { if (ustr) {
char *str = (char *)id3_ucs4_utf8duplicate(ustr); MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
n = UTF8CTOWX(str); n = UTF8CTOWX(str.get());
free(str);
} }
ustr = id3_field_getstring(&frame->fields[2]); ustr = id3_field_getstring(&frame->fields[2]);
@ -368,9 +367,8 @@ void MP3ImportFileHandle::ImportID3(Tags *tags)
} }
if (ustr) { if (ustr) {
char *str = (char *)id3_ucs4_utf8duplicate(ustr); MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
v = UTF8CTOWX(str); v = UTF8CTOWX(str.get());
free(str);
} }
if (!n.IsEmpty() && !v.IsEmpty()) { if (!n.IsEmpty() && !v.IsEmpty()) {

View File

@ -324,6 +324,11 @@ How do you want to import the current file(s)?"), oldCopyPref == wxT("copy") ? _
return oldCopyPref; return oldCopyPref;
} }
struct id3_tag_deleter {
void operator () (id3_tag *p) const { if (p) id3_tag_delete(p); }
};
using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory, ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
TrackHolders &outTracks, TrackHolders &outTracks,
Tags *tags) Tags *tags)
@ -584,14 +589,17 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
continue; continue;
} }
id3_byte_t *buffer = (id3_byte_t *)malloc(len);
if (!buffer) {
break;
}
f.Read(buffer, len); id3_tag_holder tp;
struct id3_tag *tp = id3_tag_parse(buffer, len); {
free(buffer); ArrayOf<id3_byte_t> buffer{ len };
if (!buffer) {
break;
}
f.Read(buffer.get(), len);
tp.reset( id3_tag_parse(buffer.get(), len) );
}
if (!tp) { if (!tp) {
break; break;
@ -662,9 +670,8 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
else if (frame->nfields == 3) { else if (frame->nfields == 3) {
ustr = id3_field_getstring(&frame->fields[1]); ustr = id3_field_getstring(&frame->fields[1]);
if (ustr) { if (ustr) {
char *str = (char *)id3_ucs4_utf8duplicate(ustr); MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
n = UTF8CTOWX(str); n = UTF8CTOWX(str.get());
free(str);
} }
ustr = id3_field_getstring(&frame->fields[2]); ustr = id3_field_getstring(&frame->fields[2]);
@ -674,9 +681,8 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
} }
if (ustr) { if (ustr) {
char *str = (char *)id3_ucs4_utf8duplicate(ustr); MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
v = UTF8CTOWX(str); v = UTF8CTOWX(str.get());
free(str);
} }
if (!n.IsEmpty() && !v.IsEmpty()) { if (!n.IsEmpty() && !v.IsEmpty()) {
@ -692,7 +698,6 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
} }
} }
id3_tag_delete(tp);
break; break;
} }

View File

@ -319,18 +319,22 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
format = floatSample; format = floatSample;
break; break;
} }
AudioBufferList *abl = (AudioBufferList *) std::unique_ptr<AudioBufferList, freer> abl
calloc(1, offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * numchan)); { static_cast<AudioBufferList *>
(calloc(1, offsetof(AudioBufferList, mBuffers) +
(sizeof(AudioBuffer) * numchan))) };
abl->mNumberBuffers = numchan; abl->mNumberBuffers = numchan;
TrackHolders channels{ numchan }; TrackHolders channels{ numchan };
ArraysOf<unsigned char> holders{ numchan, sizeof(float) * bufsize };
int c; int c;
for (c = 0; c < numchan; c++) { for (c = 0; c < numchan; c++) {
abl->mBuffers[c].mNumberChannels = 1; abl->mBuffers[c].mNumberChannels = 1;
abl->mBuffers[c].mDataByteSize = sizeof(float) * bufsize; abl->mBuffers[c].mDataByteSize = sizeof(float) * bufsize;
abl->mBuffers[c].mData = malloc(abl->mBuffers[c].mDataByteSize);
abl->mBuffers[c].mData = holders[c].get();
channels[c] = trackFactory->NewWaveTrack(format); channels[c] = trackFactory->NewWaveTrack(format);
channels[c]->SetRate(desc.mSampleRate); channels[c]->SetRate(desc.mSampleRate);
@ -352,7 +356,7 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
err = MovieAudioExtractionFillBuffer(maer, err = MovieAudioExtractionFillBuffer(maer,
&numFrames, &numFrames,
abl, abl.get(),
&flags); &flags);
if (err != noErr) { if (err != noErr) {
wxMessageBox(_("Unable to get fill buffer")); wxMessageBox(_("Unable to get fill buffer"));
@ -383,12 +387,7 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
outTracks.swap(channels); outTracks.swap(channels);
} }
for (c = 0; c < numchan; c++) {
free(abl->mBuffers[c].mData);
}
free(abl);
// //
// Extract any metadata // Extract any metadata
// //
@ -463,7 +462,6 @@ void QTImportFileHandle::AddMetadata(Tags *tags)
continue; continue;
} }
QTPropertyValuePtr outValPtr = nil;
QTPropertyValueType outPropType; QTPropertyValueType outPropType;
::ByteCount outPropValueSize; ::ByteCount outPropValueSize;
::ByteCount outPropValueSizeUsed = 0; ::ByteCount outPropValueSizeUsed = 0;
@ -495,7 +493,7 @@ void QTImportFileHandle::AddMetadata(Tags *tags)
} }
// Alloc memory for it // Alloc memory for it
outValPtr = malloc(outPropValueSize); ArrayOf<char> outVals{ outPropValueSize };
// Retrieve the data // Retrieve the data
err = QTMetaDataGetItemProperty(metaDataRef, err = QTMetaDataGetItemProperty(metaDataRef,
@ -503,24 +501,22 @@ void QTImportFileHandle::AddMetadata(Tags *tags)
kPropertyClass_MetaDataItem, kPropertyClass_MetaDataItem,
kQTMetaDataItemPropertyID_Value, kQTMetaDataItemPropertyID_Value,
outPropValueSize, outPropValueSize,
outValPtr, outVals.get(),
&outPropValueSizeUsed); &outPropValueSizeUsed);
if (err != noErr) { if (err != noErr)
free(outValPtr);
continue; continue;
}
wxString v = wxT(""); wxString v = wxT("");
switch (dataType) switch (dataType)
{ {
case kQTMetaDataTypeUTF8: case kQTMetaDataTypeUTF8:
v = wxString((char *)outValPtr, wxConvUTF8); v = wxString(outVals.get(), wxConvUTF8);
break; break;
case kQTMetaDataTypeUTF16BE: case kQTMetaDataTypeUTF16BE:
{ {
wxMBConvUTF16BE conv; wxMBConvUTF16BE conv;
v = wxString((char *)outValPtr, conv); v = wxString(outVals.get(), conv);
} }
break; break;
} }
@ -528,8 +524,6 @@ void QTImportFileHandle::AddMetadata(Tags *tags)
if (!v.IsEmpty()) { if (!v.IsEmpty()) {
tags->SetTag(names[i].name, v); tags->SetTag(names[i].name, v);
} }
free(outValPtr);
} }
// we are done so release our metadata object // we are done so release our metadata object

View File

@ -13,7 +13,9 @@
**********************************************************************/ **********************************************************************/
#include "../Audacity.h"
#include "RawAudioGuess.h" #include "RawAudioGuess.h"
#include "../MemoryX.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -31,10 +33,9 @@
static FILE *g_raw_debug_file = NULL; static FILE *g_raw_debug_file = NULL;
#endif #endif
static float AmpStat(float *data, int len) static float AmpStat(float *data, size_t len)
{ {
float sum, sumofsquares, avg, variance, dev; float sum, sumofsquares, avg, variance, dev;
int i;
if (len == 0) if (len == 0)
return 1.0; return 1.0;
@ -44,7 +45,7 @@ static float AmpStat(float *data, int len)
sum = 0.0; sum = 0.0;
sumofsquares = 0.0; sumofsquares = 0.0;
for (i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
float x = fabs(data[i]); float x = fabs(data[i]);
sum += x; sum += x;
sumofsquares += x * x; sumofsquares += x * x;
@ -58,31 +59,29 @@ static float AmpStat(float *data, int len)
return dev; return dev;
} }
static float JumpStat(float *data, int len) static float JumpStat(float *data, size_t len)
{ {
float avg; float avg;
int i;
/* Calculate 1.0 - avg jump /* Calculate 1.0 - avg jump
* A score near 1.0 means avg jump is pretty small * A score near 1.0 means avg jump is pretty small
*/ */
avg = 0.0; avg = 0.0;
for (i = 0; i < len - 1; i++) for (size_t i = 0; i + 1 < len; i++)
avg += fabs(data[i + 1] - data[i]); avg += fabs(data[i + 1] - data[i]);
avg = 1.0 - (avg / (len - 1) / 2.0); avg = 1.0 - (avg / (len - 1) / 2.0);
return avg; return avg;
} }
static float SecondDStat(float *data, int len) static float SecondDStat(float *data, size_t len)
{ {
int i;
float v1=0, v2=0; float v1=0, v2=0;
float a1=0, a2=0; float a1=0, a2=0;
float sum=0; float sum=0;
for (i = 1; i < len; i++) { for (size_t i = 1; i < len; i++) {
a2 = a1; a2 = a1;
v2 = v1; v2 = v1;
v1 = data[i]-data[i-1]; v1 = data[i]-data[i-1];
@ -93,12 +92,11 @@ static float SecondDStat(float *data, int len)
return sum/len; return sum/len;
} }
static float RedundantStereo(float *data, int len) static float RedundantStereo(float *data, size_t len)
{ {
int i;
int c = 0; int c = 0;
for (i = 1; i < len - 1; i += 2) for (size_t i = 1; i + 1 < len; i += 2)
if (fabs(data[i + 1] - data[i]) > 2*fabs(data[i] - data[i - 1]) || if (fabs(data[i + 1] - data[i]) > 2*fabs(data[i] - data[i - 1]) ||
2*fabs(data[i + 1] - data[i]) < fabs(data[i] - data[i - 1])) 2*fabs(data[i + 1] - data[i]) < fabs(data[i] - data[i - 1]))
c++; c++;
@ -109,14 +107,13 @@ static float RedundantStereo(float *data, int len)
static void ExtractFloats(bool doublePrec, static void ExtractFloats(bool doublePrec,
bool bigendian, bool bigendian,
bool stereo, bool stereo,
int offset, size_t offset,
char *rawData, int dataSize, char *rawData, size_t dataSize,
float *data1, float *data2, int *len1, int *len2) float *data1, float *data2, size_t *len1, size_t *len2)
{ {
int rawCount = 0; size_t rawCount = 0;
int dataCount1 = 0; size_t dataCount1 = 0;
int dataCount2 = 0; size_t dataCount2 = 0;
int i;
bool swap; bool swap;
*len1 = 0; *len1 = 0;
@ -124,7 +121,7 @@ static void ExtractFloats(bool doublePrec,
if (offset) { if (offset) {
rawData += offset; rawData += offset;
dataSize -= offset; dataSize -= std::min(dataSize, offset);
} }
#if WORDS_BIGENDIAN #if WORDS_BIGENDIAN
@ -142,10 +139,10 @@ static void ExtractFloats(bool doublePrec,
u.d = 0.0f; u.d = 0.0f;
while (rawCount + 7 < dataSize) { while (rawCount + 7 < dataSize) {
if (swap) if (swap)
for(i=0; i<8; i++) for(size_t i = 0; i < 8; i++)
u.c[7-i] = rawData[rawCount+i]; u.c[7-i] = rawData[rawCount+i];
else else
for(i=0; i<8; i++) for(size_t i = 0; i < 8; i++)
u.c[i] = rawData[rawCount+i]; u.c[i] = rawData[rawCount+i];
data1[dataCount1] = (float)u.d; data1[dataCount1] = (float)u.d;
dataCount1++; dataCount1++;
@ -161,10 +158,10 @@ static void ExtractFloats(bool doublePrec,
u.f = 0.0f; u.f = 0.0f;
while (rawCount + 3 < dataSize) { while (rawCount + 3 < dataSize) {
if (swap) if (swap)
for(i=0; i<4; i++) for(size_t i = 0; i < 4; i++)
u.c[3-i] = rawData[rawCount+i]; u.c[3-i] = rawData[rawCount+i];
else else
for(i=0; i<4; i++) for(size_t i = 0; i < 4; i++)
u.c[i] = rawData[rawCount+i]; u.c[i] = rawData[rawCount+i];
data1[dataCount1] = u.f; data1[dataCount1] = u.f;
dataCount1++; dataCount1++;
@ -174,7 +171,7 @@ static void ExtractFloats(bool doublePrec,
if (stereo) { if (stereo) {
dataCount1 /= 2; dataCount1 /= 2;
for(i=0; i<dataCount1; i++) { for(size_t i = 0; i < dataCount1; i++) {
data2[i] = data1[2*i+1]; data2[i] = data1[2*i+1];
data1[i] = data1[2*i]; data1[i] = data1[2*i];
} }
@ -191,12 +188,11 @@ static void Extract(bool bits16,
bool bigendian, bool bigendian,
bool offset, bool offset,
char *rawData, int dataSize, char *rawData, int dataSize,
float *data1, float *data2, int *len1, int *len2) float *data1, float *data2, size_t *len1, size_t *len2)
{ {
int rawCount = 0; size_t rawCount = 0;
int dataCount1 = 0; size_t dataCount1 = 0;
int dataCount2 = 0; size_t dataCount2 = 0;
int i;
*len1 = 0; *len1 = 0;
*len2 = 0; *len2 = 0;
@ -275,7 +271,7 @@ static void Extract(bool bits16,
if (stereo) { if (stereo) {
dataCount1 /= 2; dataCount1 /= 2;
for(i=0; i<dataCount1; i++) { for(size_t i = 0; i < dataCount1; i++) {
data2[i] = data1[2*i+1]; data2[i] = data1[2*i+1];
data1[i] = data1[2*i]; data1[i] = data1[2*i];
} }
@ -286,33 +282,27 @@ static void Extract(bool bits16,
*len2 = dataCount2; *len2 = dataCount2;
} }
static int GuessFloatFormats(int numTests, char **rawData, int dataSize, static int GuessFloatFormats(unsigned numTests, const ArrayOf<char> rawData[], size_t dataSize,
int *out_offset, unsigned *out_channels) size_t *out_offset, unsigned *out_channels)
{ {
int format; int format;
int bestOffset = 0; size_t bestOffset = 0;
int bestEndian = 0; int bestEndian = 0;
int bestPrec = 0; int bestPrec = 0;
float bestSmoothAvg = 1000.0; float bestSmoothAvg = 1000.0;
int offset; size_t len1;
int endian; size_t len2;
int prec;
float *data1, *data2;
int len1;
int len2;
int test;
int i;
bool guessStereo = false; bool guessStereo = false;
int stereoVotes = 0; unsigned stereoVotes = 0;
int monoVotes = 0; unsigned monoVotes = 0;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
FILE *af = g_raw_debug_file; FILE *af = g_raw_debug_file;
fprintf(af, "Testing float\n"); fprintf(af, "Testing float\n");
#endif #endif
data1 = (float *)malloc((dataSize + 4) * sizeof(float)); ArrayOf<float> data1{ dataSize + 4 };
data2 = (float *)malloc((dataSize + 4) * sizeof(float)); ArrayOf<float> data2{ dataSize + 4 };
/* /*
* First determine if it is possibly in a floating-point * First determine if it is possibly in a floating-point
@ -332,28 +322,29 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
* floats with a 1-byte offset. * floats with a 1-byte offset.
*/ */
for(prec=0; prec<2; prec++) { for(int prec = 0; prec < 2; prec++) {
for(endian=0; endian<2; endian++) { for(int endian = 0; endian < 2; endian++) {
for(offset=0; offset<(4*prec+4); offset++) { for(size_t offset = 0; offset < (4 * prec + 4); offset++) {
int finiteVotes = 0; unsigned finiteVotes = 0;
int maxminVotes = 0; unsigned maxminVotes = 0;
float smoothAvg = 0; float smoothAvg = 0;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "prec=%d endian=%d offset=%d\n", fprintf(af, "prec=%d endian=%d offset=%d\n",
prec, endian, offset); prec, endian, (int)offset);
#endif #endif
for(test=0; test<numTests; test++) { for(unsigned test = 0; test < numTests; test++) {
float min, max; float min, max;
ExtractFloats(prec?true:false, endian?true:false, ExtractFloats(prec == 1, endian == 1,
true, /* stereo */ true, /* stereo */
offset, offset,
rawData[test], dataSize, rawData[test].get(), dataSize,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
for(i=0; i<len1; i++) size_t i = 0;
for(; i < len1; i++)
if (!(data1[i]>=0 || data1[i]<=0) || if (!(data1[i]>=0 || data1[i]<=0) ||
!(data2[i]>=0 || data2[i]<=0)) !(data2[i]>=0 || data2[i]<=0))
break; break;
@ -362,13 +353,13 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
min = data1[0]; min = data1[0];
max = data1[0]; max = data1[0];
for(i=1; i<len1; i++) { for(i = 1; i < len1; i++) {
if (data1[i]<min) if (data1[i]<min)
min = data1[i]; min = data1[i];
if (data1[i]>max) if (data1[i]>max)
max = data1[i]; max = data1[i];
} }
for(i=1; i<len2; i++) { for(i = 1; i < len2; i++) {
if (data2[i]<min) if (data2[i]<min)
min = data2[i]; min = data2[i];
if (data2[i]>max) if (data2[i]>max)
@ -379,13 +370,13 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
max > 0.01 && max <= 100000) max > 0.01 && max <= 100000)
maxminVotes++; maxminVotes++;
smoothAvg += SecondDStat(data1, len1) / max; smoothAvg += SecondDStat(data1.get(), len1) / max;
} }
smoothAvg /= numTests; smoothAvg /= numTests;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "finite: %d/%d maxmin: %d/%d smooth: %f\n", fprintf(af, "finite: %ud/%ud maxmin: %ud/%ud smooth: %f\n",
finiteVotes, numTests, maxminVotes, numTests, finiteVotes, numTests, maxminVotes, numTests,
smoothAvg); smoothAvg);
#endif #endif
@ -410,11 +401,8 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
* main function will try guessing an integer format. * main function will try guessing an integer format.
*/ */
if (bestSmoothAvg >= 1000.0) { if (bestSmoothAvg >= 1000.0)
free(data1);
free(data2);
return 0; return 0;
}
/* /*
* We still have to test for mono/stereo. For an explanation * We still have to test for mono/stereo. For an explanation
@ -422,22 +410,22 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
* tests for 8-bit or 16-bit data. * tests for 8-bit or 16-bit data.
*/ */
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float leftChannel, rightChannel, combinedChannel; float leftChannel, rightChannel, combinedChannel;
ExtractFloats(bestPrec?true:false, bestEndian?true:false, ExtractFloats(bestPrec == 1, bestEndian == 1,
true, /* stereo */ true, /* stereo */
bestOffset, bestOffset,
rawData[test], dataSize, rawData[test].get(), dataSize,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
leftChannel = JumpStat(data1, len1); leftChannel = JumpStat(data1.get(), len1);
rightChannel = JumpStat(data2, len2); rightChannel = JumpStat(data2.get(), len2);
ExtractFloats(bestPrec?true:false, bestEndian?true:false, ExtractFloats(bestPrec == 1, bestEndian == 1,
false, /* stereo */ false, /* stereo */
bestOffset, bestOffset,
rawData[test], dataSize, rawData[test].get(), dataSize,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
combinedChannel = JumpStat(data1, len1); combinedChannel = JumpStat(data1.get(), len1);
if (leftChannel > combinedChannel if (leftChannel > combinedChannel
&& rightChannel > combinedChannel) && rightChannel > combinedChannel)
@ -447,30 +435,27 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "stereo: %d mono: %d\n", stereoVotes, monoVotes); fprintf(af, "stereo: %ud mono: %ud\n", stereoVotes, monoVotes);
#endif #endif
if (stereoVotes > monoVotes) guessStereo = (stereoVotes > monoVotes);
guessStereo = true;
else
guessStereo = false;
if (guessStereo == false) { if (!guessStereo) {
/* test for repeated-byte, redundant stereo */ /* test for repeated-byte, redundant stereo */
int rstereoVotes = 0; unsigned rstereoVotes = 0;
int rmonoVotes = 0; unsigned rmonoVotes = 0;
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float redundant; float redundant;
ExtractFloats(bestPrec?true:false, bestEndian?true:false, ExtractFloats(bestPrec == 1, bestEndian == 1,
false, /* stereo */ false, /* stereo */
bestOffset, bestOffset,
rawData[test], dataSize, rawData[test].get(), dataSize,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
redundant = RedundantStereo(data1, len1); redundant = RedundantStereo(data1.get(), len1);
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "redundant: %f\n", redundant); fprintf(af, "redundant: %f\n", redundant);
@ -483,11 +468,10 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "rstereo: %d rmono: %d\n", rstereoVotes, rmonoVotes); fprintf(af, "rstereo: %ud rmono: %ud\n", rstereoVotes, rmonoVotes);
#endif #endif
if (rstereoVotes > rmonoVotes) guessStereo = (rstereoVotes > rmonoVotes);
guessStereo = true;
} }
@ -515,25 +499,22 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
else else
format |= SF_ENDIAN_LITTLE; format |= SF_ENDIAN_LITTLE;
free(data1);
free(data2);
return format; return format;
} }
static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_channels) static int Guess8Bit(unsigned numTests, const ArrayOf<char> rawData[], size_t dataSize, unsigned *out_channels)
{ {
bool guessSigned = false; bool guessSigned = false;
bool guessStereo = false; bool guessStereo = false;
int signvotes = 0; unsigned signvotes = 0;
int unsignvotes = 0; unsigned unsignvotes = 0;
int stereoVotes = 0; unsigned stereoVotes = 0;
int monoVotes = 0; unsigned monoVotes = 0;
float *data1 = (float *)malloc((dataSize + 4) * sizeof(float));
float *data2 = (float *)malloc((dataSize + 4) * sizeof(float)); ArrayOf<float> data1 { dataSize + 4 };
int len1; ArrayOf<float> data2 { dataSize + 4 };
int len2; size_t len1;
int test; size_t len2;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
FILE *af = g_raw_debug_file; FILE *af = g_raw_debug_file;
@ -551,19 +532,19 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
* and returns a value 0-1. 0 is maximally discontinuous, 1 is smooth. * and returns a value 0-1. 0 is maximally discontinuous, 1 is smooth.
*/ */
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float signL, signR, unsignL, unsignR; float signL, signR, unsignL, unsignR;
Extract(0, 1, 1, 0, /* 8-bit signed stereo */ Extract(0, 1, 1, 0, /* 8-bit signed stereo */
false, rawData[test], dataSize, false, rawData[test].get(), dataSize,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
signL = JumpStat(data1, len1); signL = JumpStat(data1.get(), len1);
signR = JumpStat(data2, len2); signR = JumpStat(data2.get(), len2);
Extract(0, 0, 1, 0, /* 8-bit unsigned stereo */ Extract(0, 0, 1, 0, /* 8-bit unsigned stereo */
false, rawData[test], dataSize, false, rawData[test].get(), dataSize,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
unsignL = JumpStat(data1, len1); unsignL = JumpStat(data1.get(), len1);
unsignR = JumpStat(data2, len2); unsignR = JumpStat(data2.get(), len2);
if (signL > unsignL) if (signL > unsignL)
signvotes++; signvotes++;
@ -577,13 +558,10 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "sign: %d unsign: %d\n", signvotes, unsignvotes); fprintf(af, "sign: %ud unsign: %ud\n", signvotes, unsignvotes);
#endif #endif
if (signvotes > unsignvotes) guessSigned = (signvotes > unsignvotes);
guessSigned = true;
else
guessSigned = false;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
if (guessSigned) if (guessSigned)
@ -598,16 +576,16 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
* the entire stream interpreted as one channel. * the entire stream interpreted as one channel.
*/ */
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float leftChannel, rightChannel, combinedChannel; float leftChannel, rightChannel, combinedChannel;
Extract(0, guessSigned, 1, 0, 0, rawData[test], dataSize, data1, Extract(0, guessSigned, 1, 0, 0, rawData[test].get(), dataSize, data1.get(),
data2, &len1, &len2); data2.get(), &len1, &len2);
leftChannel = JumpStat(data1, len1); leftChannel = JumpStat(data1.get(), len1);
rightChannel = JumpStat(data2, len2); rightChannel = JumpStat(data2.get(), len2);
Extract(0, guessSigned, 0, 0, 0, rawData[test], dataSize, data1, Extract(0, guessSigned, 0, 0, 0, rawData[test].get(), dataSize, data1.get(),
data2, &len1, &len2); data2.get(), &len1, &len2);
combinedChannel = JumpStat(data1, len1); combinedChannel = JumpStat(data1.get(), len1);
if (leftChannel > combinedChannel if (leftChannel > combinedChannel
&& rightChannel > combinedChannel) && rightChannel > combinedChannel)
@ -617,27 +595,24 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "stereo: %d mono: %d\n", stereoVotes, monoVotes); fprintf(af, "stereo: %ud mono: %ud\n", stereoVotes, monoVotes);
#endif #endif
if (stereoVotes > monoVotes) guessStereo = (stereoVotes > monoVotes);
guessStereo = true;
else
guessStereo = false;
if (guessStereo == false) { if (!guessStereo) {
/* test for repeated-byte, redundant stereo */ /* test for repeated-byte, redundant stereo */
int rstereoVotes = 0; unsigned rstereoVotes = 0;
int rmonoVotes = 0; unsigned rmonoVotes = 0;
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float redundant; float redundant;
Extract(0, guessSigned, 0, 0, 0, rawData[test], dataSize, Extract(0, guessSigned, 0, 0, 0, rawData[test].get(), dataSize,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
redundant = RedundantStereo(data1, len1); redundant = RedundantStereo(data1.get(), len1);
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "redundant: %f\n", redundant); fprintf(af, "redundant: %f\n", redundant);
@ -650,11 +625,10 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "rstereo: %d rmono: %d\n", rstereoVotes, rmonoVotes); fprintf(af, "rstereo: %ud rmono: %ud\n", rstereoVotes, rmonoVotes);
#endif #endif
if (rstereoVotes > rmonoVotes) guessStereo = (rstereoVotes > rmonoVotes);
guessStereo = true;
} }
@ -665,9 +639,6 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
fprintf(af, "mono\n"); fprintf(af, "mono\n");
#endif #endif
free(data1);
free(data2);
if (guessStereo) if (guessStereo)
*out_channels = 2; *out_channels = 2;
else else
@ -679,27 +650,26 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
return SF_FORMAT_RAW | SF_FORMAT_PCM_U8; return SF_FORMAT_RAW | SF_FORMAT_PCM_U8;
} }
static int Guess16Bit(int numTests, char **rawData, static int Guess16Bit(unsigned numTests, const ArrayOf<char> rawData[],
int dataSize, bool evenMSB, size_t dataSize, bool evenMSB,
int *out_offset, unsigned *out_channels) size_t *out_offset, unsigned *out_channels)
{ {
int format; int format;
bool guessSigned = false; bool guessSigned = false;
bool guessStereo = false; bool guessStereo = false;
bool guessBigEndian = false; bool guessBigEndian = false;
bool guessOffset = false; bool guessOffset = false;
int signvotes = 0; unsigned signvotes = 0;
int unsignvotes = 0; unsigned unsignvotes = 0;
int stereoVotes = 0; unsigned stereoVotes = 0;
int monoVotes = 0; unsigned monoVotes = 0;
int formerVotes = 0; unsigned formerVotes = 0;
int latterVotes = 0; unsigned latterVotes = 0;
char *rawData2 = (char *)malloc(dataSize + 4); ArrayOf<char> rawData2{ dataSize + 4 };
float *data1 = (float *)malloc((dataSize + 4) * sizeof(float)); ArrayOf<float> data1{ dataSize + 4 };
float *data2 = (float *)malloc((dataSize + 4) * sizeof(float)); ArrayOf<float> data2{ dataSize + 4 };
int len1; size_t len1;
int len2; size_t len2;
int test;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
FILE *af = g_raw_debug_file; FILE *af = g_raw_debug_file;
@ -710,26 +680,25 @@ static int Guess16Bit(int numTests, char **rawData,
* Do the signed/unsigned test by using only the MSB. * Do the signed/unsigned test by using only the MSB.
*/ */
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float signL, signR, unsignL, unsignR; float signL, signR, unsignL, unsignR;
int i;
/* Extract a NEW array of the MSBs only: */ /* Extract a NEW array of the MSBs only: */
for (i = 0; i < dataSize / 2; i++) for (size_t i = 0; i < dataSize / 2; i++)
rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)]; rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)];
/* Test signed/unsigned of the MSB */ /* Test signed/unsigned of the MSB */
Extract(0, 1, 1, 0, /* 8-bit signed stereo */ Extract(0, 1, 1, 0, /* 8-bit signed stereo */
0, rawData2, dataSize / 2, data1, data2, &len1, &len2); 0, rawData2.get(), dataSize / 2, data1.get(), data2.get(), &len1, &len2);
signL = JumpStat(data1, len1); signL = JumpStat(data1.get(), len1);
signR = JumpStat(data2, len2); signR = JumpStat(data2.get(), len2);
Extract(0, 0, 1, 0, /* 8-bit unsigned stereo */ Extract(0, 0, 1, 0, /* 8-bit unsigned stereo */
0, rawData2, dataSize / 2, data1, data2, &len1, &len2); 0, rawData2.get(), dataSize / 2, data1.get(), data2.get(), &len1, &len2);
unsignL = JumpStat(data1, len1); unsignL = JumpStat(data1.get(), len1);
unsignR = JumpStat(data2, len2); unsignR = JumpStat(data2.get(), len2);
if (signL > unsignL) if (signL > unsignL)
signvotes++; signvotes++;
@ -743,13 +712,10 @@ static int Guess16Bit(int numTests, char **rawData,
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "sign: %d unsign: %d\n", signvotes, unsignvotes); fprintf(af, "sign: %ud unsign: %ud\n", signvotes, unsignvotes);
#endif #endif
if (signvotes > unsignvotes) guessSigned = (signvotes > unsignvotes);
guessSigned = true;
else
guessSigned = false;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
if (guessSigned) if (guessSigned)
@ -762,22 +728,21 @@ static int Guess16Bit(int numTests, char **rawData,
* Test mono/stereo using only the MSB * Test mono/stereo using only the MSB
*/ */
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float leftChannel, rightChannel, combinedChannel; float leftChannel, rightChannel, combinedChannel;
int i;
/* Extract a NEW array of the MSBs only: */ /* Extract a NEW array of the MSBs only: */
for (i = 0; i < dataSize / 2; i++) for (size_t i = 0; i < dataSize / 2; i++)
rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)]; rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)];
Extract(0, guessSigned, 1, 0, 0, Extract(0, guessSigned, 1, 0, 0,
rawData2, dataSize / 2, data1, data2, &len1, &len2); rawData2.get(), dataSize / 2, data1.get(), data2.get(), &len1, &len2);
leftChannel = JumpStat(data1, len1); leftChannel = JumpStat(data1.get(), len1);
rightChannel = JumpStat(data2, len2); rightChannel = JumpStat(data2.get(), len2);
Extract(0, guessSigned, 0, 0, 0, Extract(0, guessSigned, 0, 0, 0,
rawData2, dataSize / 2, data1, data2, &len1, &len2); rawData2.get(), dataSize / 2, data1.get(), data2.get(), &len1, &len2);
combinedChannel = JumpStat(data1, len1); combinedChannel = JumpStat(data1.get(), len1);
if (leftChannel > combinedChannel if (leftChannel > combinedChannel
&& rightChannel > combinedChannel) && rightChannel > combinedChannel)
@ -787,35 +752,31 @@ static int Guess16Bit(int numTests, char **rawData,
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "stereoVotes: %d monoVotes: %d\n", stereoVotes, monoVotes); fprintf(af, "stereoVotes: %ud monoVotes: %ud\n", stereoVotes, monoVotes);
#endif #endif
if (stereoVotes > monoVotes) guessStereo = (stereoVotes > monoVotes);
guessStereo = true;
else
guessStereo = false;
if (guessStereo == false) { if (!guessStereo) {
/* Test for repeated-byte, redundant stereo */ /* Test for repeated-byte, redundant stereo */
int rstereoVotes = 0; unsigned rstereoVotes = 0;
int rmonoVotes = 0; unsigned rmonoVotes = 0;
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float redundant; float redundant;
int i;
/* Extract a NEW array of the MSBs only: */ /* Extract a NEW array of the MSBs only: */
for (i = 0; i < dataSize / 2; i++) for (size_t i = 0; i < dataSize / 2; i++)
rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)]; rawData2[i] = rawData[test][2 * i + (evenMSB ? 0 : 1)];
Extract(0, guessSigned, 0, 0, 0, rawData2, dataSize / 2, Extract(0, guessSigned, 0, 0, 0, rawData2.get(), dataSize / 2,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
redundant = RedundantStereo(data1, len1); redundant = RedundantStereo(data1.get(), len1);
if (redundant > 0.8) if (redundant > 0.8)
rstereoVotes++; rstereoVotes++;
@ -824,12 +785,11 @@ static int Guess16Bit(int numTests, char **rawData,
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "rstereoVotes: %d rmonoVotes: %d\n", fprintf(af, "rstereoVotes: %ud rmonoVotes: %ud\n",
rstereoVotes, rmonoVotes); rstereoVotes, rmonoVotes);
#endif #endif
if (rstereoVotes > rmonoVotes) guessStereo = (rstereoVotes > rmonoVotes);
guessStereo = true;
} }
@ -854,29 +814,29 @@ static int Guess16Bit(int numTests, char **rawData,
fprintf(af, "evenMSB: %d BE: %d\n", evenMSB, guessBigEndian); fprintf(af, "evenMSB: %d BE: %d\n", evenMSB, guessBigEndian);
#endif #endif
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float former, latter; float former, latter;
int i, offs; int offs;
/* Extract a NEW array of the MSBs only: */ /* Extract a NEW array of the MSBs only: */
if (guessStereo) if (guessStereo)
for (i = 0; i < (dataSize/4)-1; i++) for (size_t i = 0; i + 1 < (dataSize / 4); i++)
rawData2[i] = rawData2[i] =
rawData[test][4 * i + (evenMSB ? 0 : 1)]; rawData[test][4 * i + (evenMSB ? 0 : 1)];
else else
for (i = 0; i < (dataSize/2)-1; i++) for (size_t i = 0; i + 1 < (dataSize / 2); i++)
rawData2[i] = rawData2[i] =
rawData[test][2 * i + (evenMSB ? 0 : 1)]; rawData[test][2 * i + (evenMSB ? 0 : 1)];
former = 0.0; former = 0.0;
Extract(1, guessSigned, guessStereo, guessBigEndian, guessOffset, Extract(1, guessSigned, guessStereo, guessBigEndian, guessOffset,
rawData[test], dataSize-4, data1, data2, &len1, &len2); rawData[test].get(), dataSize-4, data1.get(), data2.get(), &len1, &len2);
offs=(!guessBigEndian); offs=(!guessBigEndian);
for(i=3; i<len1-4; i++) { for(size_t i = 3; i + 4 < len1; i++) {
if (rawData2[offs+i-2]==rawData2[offs+i-1] && if (rawData2[offs+i-2]==rawData2[offs+i-1] &&
rawData2[offs+i]==rawData2[offs+i-1]+1 && rawData2[offs+i]==rawData2[offs+i-1]+1 &&
rawData2[offs+i]==rawData2[offs+i+1]) { rawData2[offs+i]==rawData2[offs+i+1]) {
@ -886,12 +846,12 @@ static int Guess16Bit(int numTests, char **rawData,
latter = 0.0; latter = 0.0;
Extract(1, guessSigned, guessStereo, !guessBigEndian, Extract(1, guessSigned, guessStereo, !guessBigEndian,
!guessOffset, rawData[test], dataSize, data1, data2, !guessOffset, rawData[test].get(), dataSize, data1.get(), data2.get(),
&len1, &len2); &len1, &len2);
offs=(guessBigEndian); offs=(guessBigEndian);
for(i=3; i<len1-4; i++) { for(size_t i = 3; i + 4 < len1; i++) {
if (rawData2[offs+i-2]==rawData2[offs+i-1] && if (rawData2[offs+i-2]==rawData2[offs+i-1] &&
rawData2[offs+i]==rawData2[offs+i-1]+1 && rawData2[offs+i]==rawData2[offs+i-1]+1 &&
rawData2[offs+i]==rawData2[offs+i+1]) { rawData2[offs+i]==rawData2[offs+i+1]) {
@ -911,7 +871,7 @@ static int Guess16Bit(int numTests, char **rawData,
} }
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "former (BE/LE): %d latter (LE+/BE+): %d\n", fprintf(af, "former (BE/LE): %ud latter (LE+/BE+): %ud\n",
formerVotes, latterVotes); formerVotes, latterVotes);
#endif #endif
@ -950,29 +910,23 @@ static int Guess16Bit(int numTests, char **rawData,
else else
*out_channels = 1; *out_channels = 1;
free(rawData2);
free(data1);
free(data2);
return format; return format;
} }
static int GuessIntFormats(int numTests, char **rawData, int dataSize, static int GuessIntFormats(unsigned numTests, const ArrayOf<char> rawData[], size_t dataSize,
int *out_offset, unsigned *out_channels) size_t *out_offset, unsigned *out_channels)
{ {
int format = SF_FORMAT_RAW; int format = SF_FORMAT_RAW;
bool guess16bit = false; bool guess16bit = false;
bool evenMSB; bool evenMSB;
float *data1 = (float *)malloc((dataSize + 4) * sizeof(float)); ArrayOf<float> data1{ dataSize + 4 };
float *data2 = (float *)malloc((dataSize + 4) * sizeof(float)); ArrayOf<float> data2{ dataSize + 4 };
int len1; size_t len1;
int len2; size_t len2;
int vote8 = 0; unsigned vote8 = 0;
int vote16 = 0; unsigned vote16 = 0;
int evenMSBVotes = 0; unsigned evenMSBVotes = 0;
int oddMSBVotes = 0; unsigned oddMSBVotes = 0;
int test;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
FILE *af = g_raw_debug_file; FILE *af = g_raw_debug_file;
@ -993,14 +947,14 @@ static int GuessIntFormats(int numTests, char **rawData, int dataSize,
* with mono or stereo data. * with mono or stereo data.
*/ */
for (test = 0; test < numTests; test++) { for (unsigned test = 0; test < numTests; test++) {
float even, odd; float even, odd;
Extract(0, 1, 1, 0, /* 8-bit signed stereo */ Extract(0, 1, 1, 0, /* 8-bit signed stereo */
false, rawData[test], dataSize, false, rawData[test].get(), dataSize,
data1, data2, &len1, &len2); data1.get(), data2.get(), &len1, &len2);
even = AmpStat(data1, len1); even = AmpStat(data1.get(), len1);
odd = AmpStat(data2, len2); odd = AmpStat(data2.get(), len2);
if ((even > 0.15) && (odd > 0.15)) { if ((even > 0.15) && (odd > 0.15)) {
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "Both appear random: %.2f, %.2f.\n", even, odd); fprintf(af, "Both appear random: %.2f, %.2f.\n", even, odd);
@ -1021,15 +975,12 @@ static int GuessIntFormats(int numTests, char **rawData, int dataSize,
evenMSB = (evenMSBVotes > oddMSBVotes); evenMSB = (evenMSBVotes > oddMSBVotes);
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fprintf(af, "evenMSBVote: %d oddMSBVote: %d\n", fprintf(af, "evenMSBVote: %ud oddMSBVote: %ud\n",
evenMSBVotes, oddMSBVotes); evenMSBVotes, oddMSBVotes);
fprintf(af, "vote8: %d vote16: %d\n", vote8, vote16); fprintf(af, "vote8: %ud vote16: %ud\n", vote8, vote16);
#endif #endif
if (vote8 > vote16) guess16bit = (vote8 <= vote16);
guess16bit = false;
else
guess16bit = true;
if (!guess16bit) if (!guess16bit)
format = Guess8Bit(numTests, rawData, dataSize, out_channels); format = Guess8Bit(numTests, rawData, dataSize, out_channels);
@ -1038,23 +989,18 @@ static int GuessIntFormats(int numTests, char **rawData, int dataSize,
dataSize, evenMSB, dataSize, evenMSB,
out_offset, out_channels); out_offset, out_channels);
free(data1);
free(data2);
return format; return format;
} }
int RawAudioGuess(const wxString &in_fname, int RawAudioGuess(const wxString &in_fname,
int *out_offset, unsigned *out_channels) size_t *out_offset, unsigned *out_channels)
{ {
const int numTests = 11; const unsigned numTests = 11;
size_t headerSkipSize = 64; size_t headerSkipSize = 64;
size_t dataSize = 16384; size_t dataSize = 16384;
int format = SF_FORMAT_RAW; int format = SF_FORMAT_RAW;
FILE *inf; FILE *inf;
size_t fileLen; size_t fileLen;
char *rawData[numTests];
int test;
size_t read_data; size_t read_data;
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
@ -1095,10 +1041,14 @@ int RawAudioGuess(const wxString &in_fname,
if (fileLen < dataSize) if (fileLen < dataSize)
dataSize = fileLen / 2; dataSize = fileLen / 2;
for (test = 0; test < numTests; test++) { wxASSERT( dataSize >= 4 );
wxASSERT( dataSize <= fileLen );
ArraysOf<char> rawData{ numTests, dataSize + 4 };
for (unsigned test = 0; test < numTests; test++) {
int startPoint; int startPoint;
rawData[test] = (char *)malloc(dataSize + 4);
startPoint = (fileLen - dataSize) * (test + 1) / (numTests + 2); startPoint = (fileLen - dataSize) * (test + 1) / (numTests + 2);
/* Make it a multiple of 16 (stereo double-precision) */ /* Make it a multiple of 16 (stereo double-precision) */
@ -1106,7 +1056,7 @@ int RawAudioGuess(const wxString &in_fname,
// FIXME: TRAP_ERR fseek return in MultiFormatReader unchecked. // FIXME: TRAP_ERR fseek return in MultiFormatReader unchecked.
fseek(inf, headerSkipSize + startPoint, SEEK_SET); fseek(inf, headerSkipSize + startPoint, SEEK_SET);
read_data = fread(rawData[test], 1, dataSize, inf); read_data = fread(rawData[test].get(), 1, dataSize, inf);
if (read_data != dataSize && ferror(inf)) { if (read_data != dataSize && ferror(inf)) {
perror("fread error in RawAudioGuess"); perror("fread error in RawAudioGuess");
} }
@ -1121,17 +1071,18 @@ int RawAudioGuess(const wxString &in_fname,
* almost anything looks like it could be integer data... * almost anything looks like it could be integer data...
*/ */
format = GuessFloatFormats(numTests, rawData, dataSize, format = GuessFloatFormats(numTests,
rawData.get(),
dataSize,
out_offset, out_channels); out_offset, out_channels);
if (format == 0) { if (format == 0) {
format = GuessIntFormats(numTests, rawData, dataSize, format = GuessIntFormats(numTests,
rawData.get(),
dataSize,
out_offset, out_channels); out_offset, out_channels);
} }
for (test = 0; test < numTests; test++)
free(rawData[test]);
#if RAW_GUESS_DEBUG #if RAW_GUESS_DEBUG
fclose(af); fclose(af);
g_raw_debug_file = NULL; g_raw_debug_file = NULL;

View File

@ -25,4 +25,4 @@
SF_FORMAT value SF_FORMAT value
*/ */
int RawAudioGuess(const wxString &in_fname, int RawAudioGuess(const wxString &in_fname,
int *out_offset, unsigned *out_channels); unsigned *out_offset, unsigned *out_channels);

View File

@ -43,10 +43,7 @@ extern FFmpegLibs *FFmpegLibsInst();
//struct for caching the decoded samples to be used over multiple blockfiles //struct for caching the decoded samples to be used over multiple blockfiles
struct FFMpegDecodeCache struct FFMpegDecodeCache
{ {
FFMpegDecodeCache() {} ArrayOf<uint8_t> samplePtr;//interleaved samples
~FFMpegDecodeCache() { free(samplePtr); }
uint8_t* samplePtr{};//interleaved samples
sampleCount start; sampleCount start;
size_t len; size_t len;
unsigned numChannels; unsigned numChannels;
@ -391,6 +388,7 @@ int ODFFmpegDecoder::Decode(SampleBuffer & data, sampleFormat & format, sampleCo
//if we've skipped over some samples, fill the gap with silence. This could happen often in the beginning of the file. //if we've skipped over some samples, fill the gap with silence. This could happen often in the beginning of the file.
if(actualDecodeStart>start && firstpass) { if(actualDecodeStart>start && firstpass) {
// find the number of samples for the leading silence // find the number of samples for the leading silence
// UNSAFE_SAMPLE_COUNT_TRUNCATION // UNSAFE_SAMPLE_COUNT_TRUNCATION
// -- but used only experimentally as of this writing // -- but used only experimentally as of this writing
// Is there a proof size_t will not overflow size_t? // Is there a proof size_t will not overflow size_t?
@ -402,7 +400,7 @@ int ODFFmpegDecoder::Decode(SampleBuffer & data, sampleFormat & format, sampleCo
//put it in the cache so the other channels can use it. //put it in the cache so the other channels can use it.
// wxASSERT(sc->m_stream->codec->channels > 0); // wxASSERT(sc->m_stream->codec->channels > 0);
cache->numChannels = sc->m_stream->codec->channels; cache->numChannels = std::max<unsigned>(0, sc->m_stream->codec->channels);
cache->len = amt; cache->len = amt;
cache->start=start; cache->start=start;
// 8 bit and 16 bit audio output from ffmpeg means // 8 bit and 16 bit audio output from ffmpeg means
@ -413,9 +411,7 @@ int ODFFmpegDecoder::Decode(SampleBuffer & data, sampleFormat & format, sampleCo
else else
cache->samplefmt = AV_SAMPLE_FMT_FLT; cache->samplefmt = AV_SAMPLE_FMT_FLT;
cache->samplePtr = (uint8_t*) malloc(amt * cache->numChannels * SAMPLE_SIZE(format)); cache->samplePtr.reinit(amt * cache->numChannels * SAMPLE_SIZE(format), true);
memset(cache->samplePtr, 0, amt * cache->numChannels * SAMPLE_SIZE(format));
InsertCache(std::move(cache)); InsertCache(std::move(cache));
} }
@ -538,27 +534,27 @@ int ODFFmpegDecoder::FillDataFromCache(samplePtr & data, sampleFormat outFormat,
{ {
case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_U8:
//printf("u8 in %lu out %lu cachelen %lu outLen %lu\n", inIndex, outIndex, mDecodeCache[i]->len, len); //printf("u8 in %lu out %lu cachelen %lu outLen %lu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((int16_t *)outBuf)[outIndex] = (int16_t) (((uint8_t*)mDecodeCache[i]->samplePtr)[inIndex] - 0x80) << 8; ((int16_t *)outBuf)[outIndex] = (int16_t) (((uint8_t*)mDecodeCache[i]->samplePtr.get())[inIndex] - 0x80) << 8;
break; break;
case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16:
//printf("u16 in %lu out %lu cachelen %lu outLen % lu\n", inIndex, outIndex, mDecodeCache[i]->len, len); //printf("u16 in %lu out %lu cachelen %lu outLen % lu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((int16_t *)outBuf)[outIndex] = ((int16_t*)mDecodeCache[i]->samplePtr)[inIndex]; ((int16_t *)outBuf)[outIndex] = ((int16_t*)mDecodeCache[i]->samplePtr.get())[inIndex];
break; break;
case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32:
//printf("s32 in %lu out %lu cachelen %lu outLen %lu\n", inIndex, outIndex, mDecodeCache[i]->len, len); //printf("s32 in %lu out %lu cachelen %lu outLen %lu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((float *)outBuf)[outIndex] = (float) ((int32_t*)mDecodeCache[i]->samplePtr)[inIndex] * (1.0 / (1u << 31)); ((float *)outBuf)[outIndex] = (float) ((int32_t*)mDecodeCache[i]->samplePtr.get())[inIndex] * (1.0 / (1u << 31));
break; break;
case AV_SAMPLE_FMT_FLT: case AV_SAMPLE_FMT_FLT:
//printf("f in %lu out %lu cachelen %lu outLen %lu\n", inIndex, outIndex, mDecodeCache[i]->len, len); //printf("f in %lu out %lu cachelen %lu outLen %lu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((float *)outBuf)[outIndex] = (float) ((float*)mDecodeCache[i]->samplePtr)[inIndex]; ((float *)outBuf)[outIndex] = (float) ((float*)mDecodeCache[i]->samplePtr.get())[inIndex];
break; break;
case AV_SAMPLE_FMT_DBL: case AV_SAMPLE_FMT_DBL:
//printf("dbl in %lu out %lu cachelen %lu outLen %lu\n", inIndex, outIndex, mDecodeCache[i]->len, len); //printf("dbl in %lu out %lu cachelen %lu outLen %lu\n", inIndex, outIndex, mDecodeCache[i]->len, len);
((float *)outBuf)[outIndex] = (float) ((double*)mDecodeCache[i]->samplePtr)[inIndex]; ((float *)outBuf)[outIndex] = (float) ((double*)mDecodeCache[i]->samplePtr.get())[inIndex];
break; break;
default: default:
@ -614,13 +610,13 @@ int ODFFmpegDecoder::DecodeFrame(streamContext *sc, bool flushing)
auto cache = make_movable<FFMpegDecodeCache>(); auto cache = make_movable<FFMpegDecodeCache>();
//len is number of samples per channel //len is number of samples per channel
// wxASSERT(sc->m_stream->codec->channels > 0); // wxASSERT(sc->m_stream->codec->channels > 0);
cache->numChannels = sc->m_stream->codec->channels; cache->numChannels = std::max<unsigned>(0, sc->m_stream->codec->channels);
cache->len = (sc->m_decodedAudioSamplesValidSiz / sc->m_samplesize) / cache->numChannels; cache->len = (sc->m_decodedAudioSamplesValidSiz / sc->m_samplesize) / cache->numChannels;
cache->start = mCurrentPos; cache->start = mCurrentPos;
cache->samplePtr = (uint8_t*) malloc(sc->m_decodedAudioSamplesValidSiz); cache->samplePtr.reinit(sc->m_decodedAudioSamplesValidSiz);
cache->samplefmt = sc->m_samplefmt; cache->samplefmt = sc->m_samplefmt;
memcpy(cache->samplePtr, sc->m_decodedAudioSamples.get(), sc->m_decodedAudioSamplesValidSiz); memcpy(cache->samplePtr.get(), sc->m_decodedAudioSamples.get(), sc->m_decodedAudioSamplesValidSiz);
InsertCache(std::move(cache)); InsertCache(std::move(cache));
} }

View File

@ -110,7 +110,7 @@ class ODLock {
private: private:
friend class ODCondition; //needs friendship for wait() friend class ODCondition; //needs friendship for wait()
pthread_mutex_t mutex ; pthread_mutex_t mutex;
}; };
class ODCondition class ODCondition

View File

@ -348,10 +348,7 @@ SpectrogramSettings::~SpectrogramSettings()
void SpectrogramSettings::DestroyWindows() void SpectrogramSettings::DestroyWindows()
{ {
if (hFFT != NULL) { hFFT.reset();
EndFFT(hFFT);
hFFT = NULL;
}
window.reset(); window.reset();
dWindow.reset(); dWindow.reset();
tWindow.reset(); tWindow.reset();
@ -420,9 +417,7 @@ void SpectrogramSettings::CacheWindows() const
const auto fftLen = WindowSize() * ZeroPaddingFactor(); const auto fftLen = WindowSize() * ZeroPaddingFactor();
const auto padding = (WindowSize() * (zeroPaddingFactor - 1)) / 2; const auto padding = (WindowSize() * (zeroPaddingFactor - 1)) / 2;
if (hFFT != NULL) hFFT = GetFFT(fftLen);
EndFFT(hFFT);
hFFT = InitializeFFT(fftLen);
RecreateWindow(window, WINDOW, fftLen, padding, windowType, windowSize, scale); RecreateWindow(window, WINDOW, fftLen, padding, windowType, windowSize, scale);
if (algorithm == algReassignment) { if (algorithm == algReassignment) {
RecreateWindow(tWindow, TWINDOW, fftLen, padding, windowType, windowSize, scale); RecreateWindow(tWindow, TWINDOW, fftLen, padding, windowType, windowSize, scale);

View File

@ -13,6 +13,7 @@ Paul Licameli
#include "../Experimental.h" #include "../Experimental.h"
#include "../SampleFormat.h" #include "../SampleFormat.h"
#include "../RealFFTf.h"
#undef SPECTRAL_SELECTION_GLOBAL_SWITCH #undef SPECTRAL_SELECTION_GLOBAL_SWITCH
@ -153,7 +154,7 @@ public:
// Following fields are derived from preferences. // Following fields are derived from preferences.
// Variables used for computing the spectrum // Variables used for computing the spectrum
mutable FFTParam *hFFT{}; mutable HFFT hFFT;
mutable Floats window; mutable Floats window;
// Two other windows for computing reassigned spectrogram // Two other windows for computing reassigned spectrogram

View File

@ -48,7 +48,7 @@
\brief An array of these created by the Ruler is used to determine \brief An array of these created by the Ruler is used to determine
what and where text annotations to the numbers on the Ruler get drawn. what and where text annotations to the numbers on the Ruler get drawn.
\todo Check whether Ruler is costing too much time in malloc/free of \todo Check whether Ruler is costing too much time in allocation/free of
array of Ruler::Label. array of Ruler::Label.
*//******************************************************************/ *//******************************************************************/