No naked malloc (calloc, strup, ...) and free!
This commit is contained in:
commit
a399d4e23a
|
@ -521,7 +521,7 @@ class GnomeShutdown
|
|||
public:
|
||||
GnomeShutdown()
|
||||
{
|
||||
mArgv[0] = strdup("Audacity");
|
||||
mArgv[0].reset(strdup("Audacity"));
|
||||
|
||||
mGnomeui = dlopen("libgnomeui-2.so.0", RTLD_NOW);
|
||||
if (!mGnomeui) {
|
||||
|
@ -550,11 +550,11 @@ class GnomeShutdown
|
|||
return;
|
||||
}
|
||||
|
||||
gnome_program_init(mArgv[0],
|
||||
gnome_program_init(mArgv[0].get(),
|
||||
"1.0",
|
||||
libgnomeui_module_info_get(),
|
||||
1,
|
||||
mArgv,
|
||||
reinterpret_cast<char**>(mArgv),
|
||||
NULL);
|
||||
|
||||
mClient = gnome_master_client();
|
||||
|
@ -568,13 +568,11 @@ class GnomeShutdown
|
|||
virtual ~GnomeShutdown()
|
||||
{
|
||||
// Do not dlclose() the libraries here lest you want segfaults...
|
||||
|
||||
free(mArgv[0]);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
char *mArgv[1];
|
||||
MallocString<> mArgv[1];
|
||||
void *mGnomeui;
|
||||
void *mGnome;
|
||||
GnomeClient *mClient;
|
||||
|
|
21
src/FFT.cpp
21
src/FFT.cpp
|
@ -113,8 +113,6 @@ void InitFFT()
|
|||
void DeinitFFT()
|
||||
{
|
||||
gFFTBitTable.reset();
|
||||
// Deallocate any unused RealFFTf tables
|
||||
CleanupFFT();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
HFFT hFFT = GetFFT(NumSamples);
|
||||
auto hFFT = GetFFT(NumSamples);
|
||||
Floats pFFT{ NumSamples };
|
||||
// Copy the data into the processing buffer
|
||||
for(size_t i = 0; i < NumSamples; i++)
|
||||
pFFT[i] = RealIn[i];
|
||||
|
||||
// Perform the FFT
|
||||
RealFFTf(pFFT.get(), hFFT);
|
||||
RealFFTf(pFFT.get(), hFFT.get());
|
||||
|
||||
// Copy the data into the real and imaginary outputs
|
||||
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];
|
||||
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,
|
||||
float *RealOut)
|
||||
{
|
||||
HFFT hFFT = GetFFT(NumSamples);
|
||||
auto hFFT = GetFFT(NumSamples);
|
||||
Floats pFFT{ NumSamples };
|
||||
// Copy the data into the processing buffer
|
||||
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];
|
||||
|
||||
// Perform the FFT
|
||||
InverseRealFFTf(pFFT.get(), hFFT);
|
||||
InverseRealFFTf(pFFT.get(), hFFT.get());
|
||||
|
||||
// Copy the data to the (purely real) output buffer
|
||||
ReorderToTime(hFFT, pFFT.get(), RealOut);
|
||||
|
||||
ReleaseFFT(hFFT);
|
||||
ReorderToTime(hFFT.get(), pFFT.get(), RealOut);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
{
|
||||
HFFT hFFT = GetFFT(NumSamples);
|
||||
auto hFFT = GetFFT(NumSamples);
|
||||
Floats pFFT{ NumSamples };
|
||||
// Copy the data into the processing buffer
|
||||
for (size_t i = 0; i<NumSamples; i++)
|
||||
pFFT[i] = In[i];
|
||||
|
||||
// Perform the FFT
|
||||
RealFFTf(pFFT.get(), hFFT);
|
||||
RealFFTf(pFFT.get(), hFFT.get());
|
||||
|
||||
// Copy the data into the real and imaginary outputs
|
||||
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
|
||||
Out[0] = pFFT[0]*pFFT[0];
|
||||
Out[NumSamples / 2] = pFFT[1]*pFFT[1];
|
||||
ReleaseFFT(hFFT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -386,10 +386,10 @@ int import_ffmpeg_decode_frame(streamContext *sc, bool flushing)
|
|||
}
|
||||
|
||||
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;
|
||||
unsigned int newsize = sc->m_samplesize * frame->nb_samples * channels;
|
||||
auto newsize = sc->m_samplesize * frame->nb_samples * channels;
|
||||
sc->m_decodedAudioSamplesValidSiz = newsize;
|
||||
// Reallocate the audio sample buffer if it's smaller than the frame size.
|
||||
if (newsize > sc->m_decodedAudioSamplesSiz )
|
||||
|
|
|
@ -982,13 +982,13 @@ struct streamContext
|
|||
int m_frameValid{}; // is m_decodedVideoFrame/m_decodedAudioSamples valid?
|
||||
AVMallocHolder<uint8_t> m_decodedAudioSamples; // decoded audio samples stored here
|
||||
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_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
|
||||
|
||||
int m_osamplesize{}; // output sample size in bytes
|
||||
size_t m_osamplesize{}; // output sample size in bytes
|
||||
sampleFormat m_osamplefmt{ floatSample }; // output sample format
|
||||
|
||||
streamContext() { memset(this, 0, sizeof(*this)); }
|
||||
|
|
|
@ -15,6 +15,8 @@ information.
|
|||
*//*******************************************************************/
|
||||
|
||||
|
||||
#include "Audacity.h"
|
||||
#include "MemoryX.h"
|
||||
#include <wx/arrstr.h>
|
||||
#include <wx/intl.h>
|
||||
#include "sndfile.h"
|
||||
|
@ -119,7 +121,6 @@ wxString sf_header_name(int format)
|
|||
wxString sf_header_shortname(int format)
|
||||
{
|
||||
SF_FORMAT_INFO format_info;
|
||||
char *tmp;
|
||||
int i;
|
||||
wxString s;
|
||||
|
||||
|
@ -127,8 +128,7 @@ wxString sf_header_shortname(int format)
|
|||
format_info.format = (format & SF_FORMAT_TYPEMASK);
|
||||
sf_command(NULL, SFC_GET_FORMAT_INFO, &format_info, sizeof(format_info));
|
||||
|
||||
tmp = (char *)malloc(strlen(format_info.name)+1);
|
||||
strcpy(tmp, format_info.name);
|
||||
MallocString<> tmp { strdup( format_info.name ) };
|
||||
i = 0;
|
||||
while(tmp[i]) {
|
||||
if (tmp[i]==' ')
|
||||
|
@ -137,9 +137,7 @@ wxString sf_header_shortname(int format)
|
|||
i++;
|
||||
}
|
||||
|
||||
s = LAT1CTOWX(tmp);
|
||||
|
||||
free(tmp);
|
||||
s = LAT1CTOWX(tmp.get());
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
107
src/RealFFTf.cpp
107
src/RealFFTf.cpp
|
@ -37,11 +37,14 @@
|
|||
*/
|
||||
|
||||
#include "Audacity.h"
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "Experimental.h"
|
||||
|
||||
#include <wx/thread.h>
|
||||
|
||||
#include "RealFFTf.h"
|
||||
#ifdef EXPERIMENTAL_EQ_SSE_THREADED
|
||||
#include "RealFFTf48x.h"
|
||||
|
@ -58,13 +61,8 @@
|
|||
HFFT InitializeFFT(size_t fftlen)
|
||||
{
|
||||
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
|
||||
* 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;
|
||||
|
||||
if((h->SinTable=(fft_type *)malloc(2*h->Points*sizeof(fft_type)))==NULL)
|
||||
{
|
||||
fprintf(stderr,"Error allocating memory for Sine table.\n");
|
||||
exit(8);
|
||||
}
|
||||
h->SinTable.reinit(2*h->Points);
|
||||
|
||||
if((h->BitReversed=(int *)malloc(h->Points*sizeof(int)))==NULL)
|
||||
{
|
||||
fprintf(stderr,"Error allocating memory for BitReversed.\n");
|
||||
exit(8);
|
||||
}
|
||||
h->BitReversed.reinit(h->Points);
|
||||
|
||||
for(size_t i = 0; i < h->Points; i++)
|
||||
{
|
||||
|
@ -109,40 +99,33 @@ HFFT InitializeFFT(size_t fftlen)
|
|||
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 };
|
||||
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 */
|
||||
/* This version keeps common tables rather than allocating a NEW table every time */
|
||||
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;
|
||||
auto n = fftlen/2;
|
||||
auto size = hFFTArray.size();
|
||||
for(;
|
||||
(h < MAX_HFFT) && (hFFTArray[h] != NULL) && (n != hFFTArray[h]->Points);
|
||||
(h < size) && hFFTArray[h] && (n != hFFTArray[h]->Points);
|
||||
h++)
|
||||
;
|
||||
if(h < MAX_HFFT) {
|
||||
if(h < size) {
|
||||
if(hFFTArray[h] == NULL) {
|
||||
hFFTArray[h] = InitializeFFT(fftlen);
|
||||
nFFTLockCount[h] = 0;
|
||||
hFFTArray[h].reset( InitializeFFT(fftlen).release() );
|
||||
}
|
||||
nFFTLockCount[h]++;
|
||||
return hFFTArray[h];
|
||||
return HFFT{ hFFTArray[h].get() };
|
||||
} else {
|
||||
// All buffers used, so fall back to allocating a NEW set of tables
|
||||
return InitializeFFT(fftlen);
|
||||
|
@ -150,31 +133,21 @@ HFFT GetFFT(size_t fftlen)
|
|||
}
|
||||
|
||||
/* Release a previously requested handle to the FFT tables */
|
||||
void ReleaseFFT(HFFT hFFT)
|
||||
void FFTDeleter::operator() (FFTParam *hFFT) const
|
||||
{
|
||||
int h;
|
||||
for(h=0; (h<MAX_HFFT) && (hFFTArray[h] != hFFT); h++);
|
||||
if(h<MAX_HFFT) {
|
||||
nFFTLockCount[h]--;
|
||||
} else {
|
||||
EndFFT(hFFT);
|
||||
}
|
||||
}
|
||||
wxCriticalSectionLocker locker{ getFFTMutex };
|
||||
|
||||
/* Deallocate any unused FFT tables */
|
||||
void CleanupFFT()
|
||||
{
|
||||
int h;
|
||||
for(h=0; (h<MAX_HFFT); h++) {
|
||||
if((nFFTLockCount[h] <= 0) && (hFFTArray[h] != NULL)) {
|
||||
EndFFT(hFFTArray[h]);
|
||||
hFFTArray[h] = NULL;
|
||||
}
|
||||
}
|
||||
auto it = hFFTArray.begin(), end = hFFTArray.end();
|
||||
while (it != end && it->get() != hFFT)
|
||||
++it;
|
||||
if ( it != end )
|
||||
;
|
||||
else
|
||||
delete hFFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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
|
||||
* 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;
|
||||
const fft_type *sptr;
|
||||
|
@ -216,7 +189,7 @@ void RealFFTf(fft_type *buffer,HFFT h)
|
|||
{
|
||||
A = buffer;
|
||||
B = buffer + ButterfliesPerGroup * 2;
|
||||
sptr = h->SinTable;
|
||||
sptr = h->SinTable.get();
|
||||
|
||||
while(A < endptr1)
|
||||
{
|
||||
|
@ -239,8 +212,8 @@ void RealFFTf(fft_type *buffer,HFFT h)
|
|||
ButterfliesPerGroup >>= 1;
|
||||
}
|
||||
/* Massage output to get the output for a real input sequence. */
|
||||
br1 = h->BitReversed + 1;
|
||||
br2 = h->BitReversed + h->Points - 1;
|
||||
br1 = h->BitReversed.get() + 1;
|
||||
br2 = h->BitReversed.get() + h->Points - 1;
|
||||
|
||||
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] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* 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;
|
||||
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. */
|
||||
A = buffer + 2;
|
||||
B = buffer + h->Points * 2 - 2;
|
||||
br1 = h->BitReversed + 1;
|
||||
br1 = h->BitReversed.get() + 1;
|
||||
while(A<B)
|
||||
{
|
||||
sin=h->SinTable[*br1];
|
||||
|
@ -353,7 +326,7 @@ void InverseRealFFTf(fft_type *buffer,HFFT h)
|
|||
{
|
||||
A = buffer;
|
||||
B = buffer + ButterfliesPerGroup * 2;
|
||||
sptr = h->SinTable;
|
||||
sptr = h->SinTable.get();
|
||||
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
for(size_t i = 0; i < hFFT->Points; i++) {
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
#ifndef __realfftf_h
|
||||
#define __realfftf_h
|
||||
|
||||
#include "Audacity.h"
|
||||
#include "Experimental.h"
|
||||
#include "MemoryX.h"
|
||||
|
||||
#define fft_type float
|
||||
using fft_type = float;
|
||||
struct FFTParam {
|
||||
int *BitReversed;
|
||||
fft_type *SinTable;
|
||||
ArrayOf<int> BitReversed;
|
||||
ArrayOf<fft_type> SinTable;
|
||||
size_t Points;
|
||||
#ifdef EXPERIMENTAL_EQ_SSE_THREADED
|
||||
int pow2Bits;
|
||||
#endif
|
||||
};
|
||||
typedef FFTParam * HFFT;
|
||||
|
||||
HFFT InitializeFFT(size_t);
|
||||
void EndFFT(HFFT);
|
||||
struct FFTDeleter{
|
||||
void operator () (FFTParam *p) const;
|
||||
};
|
||||
|
||||
using HFFT = std::unique_ptr<
|
||||
FFTParam, FFTDeleter
|
||||
>;
|
||||
|
||||
HFFT GetFFT(size_t);
|
||||
void ReleaseFFT(HFFT);
|
||||
void CleanupFFT();
|
||||
void RealFFTf(fft_type *,HFFT);
|
||||
void InverseRealFFTf(fft_type *,HFFT);
|
||||
void ReorderToTime(HFFT hFFT, const fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq(HFFT hFFT, const fft_type *buffer,
|
||||
void RealFFTf(fft_type *, const FFTParam *);
|
||||
void InverseRealFFTf(fft_type *, const FFTParam *);
|
||||
void ReorderToTime(const FFTParam *hFFT, const fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq(const FFTParam *hFFT, const fft_type *buffer,
|
||||
fft_type *RealOut, fft_type *ImagOut);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
* and BitReversed tables so they don't need to be reallocated
|
||||
* and recomputed on every call.
|
||||
* - Added Reorder* functions to undo the bit-reversal
|
||||
* Modified 15 April 2016 Paul Licameli
|
||||
* - C++11 smart pointers
|
||||
*
|
||||
* 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 */
|
||||
void RealFFTf1x(fft_type *buffer, HFFT h, int functionType)
|
||||
void RealFFTf1x(fft_type *buffer, FFTParam *h, int functionType)
|
||||
{
|
||||
switch(functionType) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
case FFT_SinCosTableVBR16:
|
||||
|
@ -318,7 +320,7 @@ void ReorderToFreq4x(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *I
|
|||
#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
|
||||
* 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
|
||||
* 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 *sptr;
|
||||
|
@ -360,7 +362,7 @@ void RealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
|
|||
{
|
||||
A = buffer;
|
||||
B = buffer + ButterfliesPerGroup * 2;
|
||||
sptr = h->SinTable;
|
||||
sptr = h->SinTable.get();
|
||||
|
||||
while(A < endptr1)
|
||||
{
|
||||
|
@ -383,8 +385,8 @@ void RealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
|
|||
ButterfliesPerGroup >>= 1;
|
||||
}
|
||||
/* Massage output to get the output for a real input sequence. */
|
||||
br1 = h->BitReversed + 1;
|
||||
br2 = h->BitReversed + h->Points - 1;
|
||||
br1 = h->BitReversed.get() + 1;
|
||||
br2 = h->BitReversed.get() + h->Points - 1;
|
||||
|
||||
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] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* 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 *sptr;
|
||||
|
@ -451,7 +453,7 @@ void InverseRealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
|
|||
/* Massage input to get the input for a real output sequence. */
|
||||
A = buffer + 2;
|
||||
B = buffer + h->Points * 2 - 2;
|
||||
br1 = h->BitReversed + 1;
|
||||
br1 = h->BitReversed.get() + 1;
|
||||
while(A < B)
|
||||
{
|
||||
sin=h->SinTable[*br1];
|
||||
|
@ -497,7 +499,7 @@ void InverseRealFFTf1xSinCosBRTable(fft_type *buffer,HFFT h)
|
|||
{
|
||||
A = buffer;
|
||||
B = buffer + ButterfliesPerGroup * 2;
|
||||
sptr = h->SinTable;
|
||||
sptr = h->SinTable.get();
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
void RealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
|
||||
void RealFFTf4xSinCosBRTable(fft_type *buffer, FFTParam *h)
|
||||
{
|
||||
|
||||
__m128 *localBuffer=(__m128 *)buffer;
|
||||
|
@ -571,7 +573,7 @@ void RealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
|
|||
{
|
||||
A = localBuffer;
|
||||
B = &localBuffer[ButterfliesPerGroup * 2];
|
||||
sptr = h->SinTable;
|
||||
sptr = h->SinTable.get();
|
||||
while(A < endptr1)
|
||||
{
|
||||
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] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* good when using fixed point arithmetic)
|
||||
*/
|
||||
void InverseRealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
|
||||
void InverseRealFFTf4xSinCosBRTable(fft_type *buffer, FFTParam *h)
|
||||
{
|
||||
|
||||
__m128 *localBuffer=(__m128 *)buffer;
|
||||
|
@ -717,7 +719,7 @@ void InverseRealFFTf4xSinCosBRTable(fft_type *buffer,HFFT h)
|
|||
{
|
||||
A = localBuffer;
|
||||
B = localBuffer + ButterfliesPerGroup * 2;
|
||||
sptr = h->SinTable;
|
||||
sptr = h->SinTable.get();
|
||||
while(A < endptr1)
|
||||
{
|
||||
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 *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);
|
||||
}
|
||||
|
||||
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 *localTimeOut=(__m128 *)TimeOut;
|
||||
|
@ -777,7 +779,7 @@ void ReorderToTime4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut
|
|||
#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
|
||||
* 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
|
||||
* 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 *endptr1,*endptr2;
|
||||
|
@ -880,7 +882,7 @@ void RealFFTf1xSinCosTableVBR16(fft_type *buffer,HFFT h)
|
|||
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* 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 *endptr1,*endptr2;
|
||||
|
@ -907,7 +909,7 @@ void InverseRealFFTf1xSinCosTableVBR16(fft_type *buffer,HFFT h)
|
|||
/* Massage input to get the input for a real output sequence. */
|
||||
A = buffer + 2;
|
||||
B = buffer + h->Points * 2 - 2;
|
||||
br1 = h->BitReversed + 1;
|
||||
br1 = h->BitReversed.get() + 1;
|
||||
br1Index = 1; //h->BitReversed + 1;
|
||||
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
|
||||
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
|
||||
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
|
||||
void RealFFTf4xSinCosTableVBR16(fft_type *buffer,HFFT h)
|
||||
void RealFFTf4xSinCosTableVBR16(fft_type *buffer, FFTParam *h)
|
||||
{
|
||||
|
||||
__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] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* good when using fixed point arithmetic)
|
||||
*/
|
||||
void InverseRealFFTf4xSinCosTableVBR16(fft_type *buffer,HFFT h)
|
||||
void InverseRealFFTf4xSinCosTableVBR16(fft_type *buffer, FFTParam *h)
|
||||
{
|
||||
|
||||
__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 *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 *localRealOut = (__m128 *)RealOut;
|
||||
|
@ -1247,7 +1249,7 @@ void ReorderToFreq4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *Real
|
|||
#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
|
||||
* 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
|
||||
* 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 *endptr1, *endptr2;
|
||||
|
@ -1354,7 +1356,7 @@ void RealFFTf1xSinCosTableBR16(fft_type *buffer,HFFT h)
|
|||
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* 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 *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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
// Copy the data into the real outputs
|
||||
|
@ -1484,7 +1486,7 @@ void ReorderToTime1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeO
|
|||
}
|
||||
|
||||
// 4x processing simd
|
||||
void RealFFTf4xSinCosTableBR16(fft_type *buffer,HFFT h)
|
||||
void RealFFTf4xSinCosTableBR16(fft_type *buffer, FFTParam *h)
|
||||
{
|
||||
|
||||
__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] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* good when using fixed point arithmetic)
|
||||
*/
|
||||
void InverseRealFFTf4xSinCosTableBR16(fft_type *buffer,HFFT h)
|
||||
void InverseRealFFTf4xSinCosTableBR16(fft_type *buffer, FFTParam *h)
|
||||
{
|
||||
|
||||
__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 *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 *localRealOut = (__m128 *)RealOut;
|
||||
|
@ -1734,7 +1736,7 @@ void ReorderToFreq4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealO
|
|||
#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
|
||||
* 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
|
||||
* 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 *endptr1, *endptr2;
|
||||
|
@ -1886,7 +1888,7 @@ void RealFFTf1xFastMathBR24(fft_type *buffer,HFFT h)
|
|||
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* 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 *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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
// 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;
|
||||
|
@ -2186,7 +2188,7 @@ void RealFFTf4xFastMathBR24(fft_type *buffer,HFFT h)
|
|||
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* good when using fixed point arithmetic)
|
||||
*/
|
||||
void InverseRealFFTf4xFastMathBR24(fft_type *buffer,HFFT h)
|
||||
void InverseRealFFTf4xFastMathBR24(fft_type *buffer, FFTParam *h)
|
||||
{
|
||||
|
||||
__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 *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);
|
||||
}
|
||||
|
||||
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 *localTimeOut = (__m128 *)TimeOut;
|
||||
|
@ -2369,7 +2371,7 @@ void ReorderToTime4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut)
|
|||
#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
|
||||
* 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
|
||||
* 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 *endptr1,*endptr2;
|
||||
|
@ -2517,7 +2519,7 @@ void RealFFTf1xFastMathBR16(fft_type *buffer,HFFT h)
|
|||
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* 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 *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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
// 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;
|
||||
|
@ -2816,7 +2818,7 @@ void RealFFTf4xFastMathBR16(fft_type *buffer,HFFT h)
|
|||
* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ]
|
||||
* wave[2*i+1] = buffer[ BitReversed[i]+1 ] )
|
||||
* 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
|
||||
* - 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
|
||||
* good when using fixed point arithmetic)
|
||||
*/
|
||||
void InverseRealFFTf4xFastMathBR16(fft_type *buffer,HFFT h)
|
||||
void InverseRealFFTf4xFastMathBR16(fft_type *buffer, FFTParam *h)
|
||||
{
|
||||
|
||||
__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 *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);
|
||||
}
|
||||
|
||||
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 *localTimeOut=(__m128 *)TimeOut;
|
||||
|
|
|
@ -16,64 +16,64 @@ enum {
|
|||
};
|
||||
|
||||
/* wrapper funcitons. If passed -1 function choice will be made locally */
|
||||
void RealFFTf1x(fft_type *,HFFT, int functionType=-1);
|
||||
void InverseRealFFTf1x(fft_type *,HFFT, int functionType=-1);
|
||||
void ReorderToTime1x(HFFT 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 RealFFTf4x(fft_type *,HFFT, int functionType=-1);
|
||||
void InverseRealFFTf4x(fft_type *,HFFT, int functionType=-1);
|
||||
void ReorderToTime4x(HFFT 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 RealFFTf1x(fft_type *, FFTParam*, int functionType=-1);
|
||||
void InverseRealFFTf1x(fft_type *, FFTParam*, int functionType=-1);
|
||||
void ReorderToTime1x(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut, int functionType=-1);
|
||||
void ReorderToFreq1x(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType=-1);
|
||||
void RealFFTf4x(fft_type *, FFTParam *, int functionType=-1);
|
||||
void InverseRealFFTf4x(fft_type *, FFTParam *, int functionType=-1);
|
||||
void ReorderToTime4x(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut, int functionType=-1);
|
||||
void ReorderToFreq4x(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut, int functionType=-1);
|
||||
|
||||
/* SinCosBRTable versions */
|
||||
void RealFFTf1xSinCosBRTable(fft_type *,HFFT);
|
||||
void InverseRealFFTf1xSinCosBRTable(fft_type *,HFFT);
|
||||
void ReorderToTime1xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xSinCosBRTable(fft_type *,HFFT);
|
||||
void InverseRealFFTf4xSinCosBRTable(fft_type *,HFFT);
|
||||
void ReorderToTime4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xSinCosBRTable(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf1xSinCosBRTable(fft_type *, FFTParam*);
|
||||
void InverseRealFFTf1xSinCosBRTable(fft_type *, FFTParam*);
|
||||
void ReorderToTime1xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xSinCosBRTable(fft_type *, FFTParam *);
|
||||
void InverseRealFFTf4xSinCosBRTable(fft_type *, FFTParam *);
|
||||
void ReorderToTime4xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xSinCosBRTable(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
|
||||
/* Fast Math BR16 versions */
|
||||
void RealFFTf1xFastMathBR16(fft_type *,HFFT);
|
||||
void InverseRealFFTf1xFastMathBR16(fft_type *,HFFT);
|
||||
void ReorderToTime1xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xFastMathBR16(fft_type *,HFFT);
|
||||
void InverseRealFFTf4xFastMathBR16(fft_type *,HFFT);
|
||||
void ReorderToTime4xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xFastMathBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf1xFastMathBR16(fft_type *, FFTParam*);
|
||||
void InverseRealFFTf1xFastMathBR16(fft_type *, FFTParam*);
|
||||
void ReorderToTime1xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xFastMathBR16(fft_type *, FFTParam *);
|
||||
void InverseRealFFTf4xFastMathBR16(fft_type *, FFTParam *);
|
||||
void ReorderToTime4xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xFastMathBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
|
||||
/* Fast Math BR24 versions */
|
||||
void RealFFTf1xFastMathBR24(fft_type *,HFFT);
|
||||
void InverseRealFFTf1xFastMathBR24(fft_type *,HFFT);
|
||||
void ReorderToTime1xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xFastMathBR24(fft_type *,HFFT);
|
||||
void InverseRealFFTf4xFastMathBR24(fft_type *,HFFT);
|
||||
void ReorderToTime4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xFastMathBR24(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf1xFastMathBR24(fft_type *, FFTParam*);
|
||||
void InverseRealFFTf1xFastMathBR24(fft_type *, FFTParam*);
|
||||
void ReorderToTime1xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xFastMathBR24(fft_type *, FFTParam *);
|
||||
void InverseRealFFTf4xFastMathBR24(fft_type *, FFTParam *);
|
||||
void ReorderToTime4xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xFastMathBR24(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
|
||||
/* SinCosTable virtual BR versions */
|
||||
void RealFFTf1xSinCosTableVBR16(fft_type *,HFFT);
|
||||
void InverseRealFFTf1xSinCosTableVBR16(fft_type *,HFFT);
|
||||
void ReorderToTime1xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xSinCosTableVBR16(fft_type *,HFFT);
|
||||
void InverseRealFFTf4xSinCosTableVBR16(fft_type *,HFFT);
|
||||
void ReorderToTime4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xSinCosTableVBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf1xSinCosTableVBR16(fft_type *, FFTParam*);
|
||||
void InverseRealFFTf1xSinCosTableVBR16(fft_type *, FFTParam*);
|
||||
void ReorderToTime1xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xSinCosTableVBR16(fft_type *, FFTParam *);
|
||||
void InverseRealFFTf4xSinCosTableVBR16(fft_type *, FFTParam *);
|
||||
void ReorderToTime4xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xSinCosTableVBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
|
||||
/* SinCosTable BR16 versions */
|
||||
void RealFFTf1xSinCosTableBR16(fft_type *,HFFT);
|
||||
void InverseRealFFTf1xSinCosTableBR16(fft_type *,HFFT);
|
||||
void ReorderToTime1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xSinCosTableBR16(fft_type *,HFFT);
|
||||
void InverseRealFFTf4xSinCosTableBR16(fft_type *,HFFT);
|
||||
void ReorderToTime4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xSinCosTableBR16(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf1xSinCosTableBR16(fft_type *, FFTParam*);
|
||||
void InverseRealFFTf1xSinCosTableBR16(fft_type *, FFTParam*);
|
||||
void ReorderToTime1xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq1xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
void RealFFTf4xSinCosTableBR16(fft_type *, FFTParam *);
|
||||
void InverseRealFFTf4xSinCosTableBR16(fft_type *, FFTParam *);
|
||||
void ReorderToTime4xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *TimeOut);
|
||||
void ReorderToFreq4xSinCosTableBR16(FFTParam *hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut);
|
||||
|
||||
void TableUsage(int iMask);
|
||||
|
||||
|
|
|
@ -41,13 +41,11 @@ Resample::Resample(const bool useBestMethod, const double dMinFactor, const doub
|
|||
mbWantConstRateResampling = false; // variable rate resampling
|
||||
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()
|
||||
{
|
||||
soxr_delete((soxr_t)mHandle);
|
||||
mHandle = NULL;
|
||||
}
|
||||
|
||||
int Resample::GetNumMethods() { return 4; }
|
||||
|
@ -85,16 +83,16 @@ std::pair<size_t, size_t>
|
|||
size_t idone, odone;
|
||||
if (mbWantConstRateResampling)
|
||||
{
|
||||
soxr_process((soxr_t)mHandle,
|
||||
soxr_process(mHandle.get(),
|
||||
inBuffer , (lastFlag? ~inBufferLen : inBufferLen), &idone,
|
||||
outBuffer, outBufferLen, &odone);
|
||||
}
|
||||
else
|
||||
{
|
||||
soxr_set_io_ratio((soxr_t)mHandle, 1/factor, 0);
|
||||
soxr_set_io_ratio(mHandle.get(), 1/factor, 0);
|
||||
|
||||
inBufferLen = lastFlag? ~inBufferLen : inBufferLen;
|
||||
soxr_process((soxr_t)mHandle,
|
||||
soxr_process(mHandle.get(),
|
||||
inBuffer , inBufferLen , &idone,
|
||||
outBuffer, outBufferLen, &odone);
|
||||
}
|
||||
|
|
|
@ -14,11 +14,19 @@
|
|||
|
||||
#include "Audacity.h"
|
||||
|
||||
#include "MemoryX.h"
|
||||
#include <wx/intl.h>
|
||||
#include <wx/string.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
|
||||
{
|
||||
public:
|
||||
|
@ -78,7 +86,7 @@ class Resample final
|
|||
|
||||
protected:
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -74,16 +74,6 @@ const wxChar *GetSampleFormatStr(sampleFormat format)
|
|||
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;
|
||||
void ClearSamples(samplePtr src, sampleFormat format,
|
||||
size_t start, size_t len)
|
||||
|
|
|
@ -49,10 +49,6 @@ const wxChar *GetSampleFormatStr(sampleFormat format);
|
|||
// 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 {
|
||||
|
||||
public:
|
||||
|
@ -60,7 +56,7 @@ public:
|
|||
: mPtr(0)
|
||||
{}
|
||||
SampleBuffer(size_t count, sampleFormat format)
|
||||
: mPtr(NewSamples(count, format))
|
||||
: mPtr((samplePtr)malloc(count * SAMPLE_SIZE(format)))
|
||||
{}
|
||||
~SampleBuffer()
|
||||
{
|
||||
|
@ -71,14 +67,14 @@ public:
|
|||
SampleBuffer &Allocate(size_t count, sampleFormat format)
|
||||
{
|
||||
Free();
|
||||
mPtr = NewSamples(count, format);
|
||||
mPtr = (samplePtr)malloc(count * SAMPLE_SIZE(format));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void Free()
|
||||
{
|
||||
DeleteSamples(mPtr);
|
||||
free(mPtr);
|
||||
mPtr = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -347,7 +347,9 @@ wxImage ThemeBase::MaskedImage( char const ** pXpm, char const ** pMask )
|
|||
|
||||
// unsigned char *src = Img1.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.
|
||||
for(i=0;i<nBytes;i++)
|
||||
|
@ -356,7 +358,7 @@ wxImage ThemeBase::MaskedImage( char const ** pXpm, char const ** pMask )
|
|||
mk+=3;
|
||||
}
|
||||
|
||||
Img1.SetAlpha( alpha);
|
||||
Img1.SetAlpha( alpha.release() );
|
||||
|
||||
//dmazzoni: the top line does not work on wxGTK
|
||||
//wxBitmap Result( Img1, 32 );
|
||||
|
|
|
@ -273,7 +273,8 @@ protected:
|
|||
};
|
||||
|
||||
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;
|
||||
if(len > hFFT->Points * 2)
|
||||
|
@ -924,7 +925,7 @@ bool SpecCache::CalculateOneSpectrum
|
|||
}
|
||||
else if (reassignment) {
|
||||
static const double epsilon = 1e-16;
|
||||
const HFFT hFFT = settings.hFFT;
|
||||
const auto hFFT = settings.hFFT.get();
|
||||
|
||||
float *const scratch2 = scratch + fftLen;
|
||||
std::copy(scratch, scratch2, scratch2);
|
||||
|
@ -1024,7 +1025,7 @@ bool SpecCache::CalculateOneSpectrum
|
|||
|
||||
// This function mutates useBuffer
|
||||
ComputeSpectrumUsingRealFFTf
|
||||
(useBuffer, settings.hFFT, settings.window.get(), fftLen, results);
|
||||
(useBuffer, settings.hFFT.get(), settings.window.get(), fftLen, results);
|
||||
if (!gainFactors.empty()) {
|
||||
// Apply a frequency-dependant gain factor
|
||||
for (size_t ii = 0; ii < nBins; ++ii)
|
||||
|
@ -1160,7 +1161,7 @@ void SpecCache::Populate
|
|||
#endif
|
||||
for (auto xx = lowerBoundX; xx < upperBoundX; ++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) {
|
||||
float &power = results[ii];
|
||||
if (power <= 0)
|
||||
|
|
|
@ -220,7 +220,7 @@ EffectEqualization::EffectEqualization()
|
|||
mCurve = NULL;
|
||||
mPanel = NULL;
|
||||
|
||||
hFFT = InitializeFFT(windowSize);
|
||||
hFFT = GetFFT(windowSize);
|
||||
|
||||
SetLinearEffectFlag(true);
|
||||
|
||||
|
@ -282,9 +282,6 @@ EffectEqualization::EffectEqualization()
|
|||
|
||||
EffectEqualization::~EffectEqualization()
|
||||
{
|
||||
if(hFFT)
|
||||
EndFFT(hFFT);
|
||||
hFFT = NULL;
|
||||
}
|
||||
|
||||
// IdentInterface implementation
|
||||
|
@ -1319,7 +1316,7 @@ void EffectEqualization::Filter(size_t len, float *buffer)
|
|||
{
|
||||
float re,im;
|
||||
// Apply FFT
|
||||
RealFFTf(buffer, hFFT);
|
||||
RealFFTf(buffer, hFFT.get());
|
||||
//FFT(len, false, inr, NULL, outr, outi);
|
||||
|
||||
// Apply filter
|
||||
|
@ -1336,8 +1333,8 @@ void EffectEqualization::Filter(size_t len, float *buffer)
|
|||
mFFTBuffer[1] = buffer[1] * mFilterFuncR[len/2];
|
||||
|
||||
// Inverse FFT and normalization
|
||||
InverseRealFFTf(mFFTBuffer.get(), hFFT);
|
||||
ReorderToTime(hFFT, mFFTBuffer.get(), buffer);
|
||||
InverseRealFFTf(mFFTBuffer.get(), hFFT.get());
|
||||
ReorderToTime(hFFT.get(), mFFTBuffer.get(), buffer);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -158,7 +158,7 @@ void * malloc_simd(const size_t size)
|
|||
#endif
|
||||
}
|
||||
|
||||
void free_simd(void* mem)
|
||||
void free_simd::operator() (void* mem) const
|
||||
{
|
||||
#if defined WIN32 // WIN32
|
||||
_aligned_free(mem);
|
||||
|
@ -169,7 +169,7 @@ void free_simd(void* mem)
|
|||
|
||||
EffectEqualization48x::EffectEqualization48x():
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ bool EffectEqualization48x::AllocateBuffersWorkers(int nThreads)
|
|||
|
||||
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
|
||||
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
|
||||
mBufferInfo.reinit(mWorkerDataCount);
|
||||
for(int i=0;i<mWorkerDataCount;i++) {
|
||||
|
@ -250,8 +250,7 @@ bool EffectEqualization48x::FreeBuffersWorkers()
|
|||
mWorkerDataCount=0;
|
||||
}
|
||||
mBufferInfo.reset();
|
||||
free_simd(mBigBuffer);
|
||||
mBigBuffer=NULL;
|
||||
mBigBuffer.reset();
|
||||
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)));
|
||||
}
|
||||
if(singleProcessLength && !bBreakLoop) {
|
||||
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, 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->Flush();
|
||||
|
@ -688,7 +687,7 @@ void EffectEqualization48x::Filter1x(size_t len,
|
|||
int i;
|
||||
float real, imag;
|
||||
// Apply FFT
|
||||
RealFFTf1x(buffer, mEffectEqualization->hFFT);
|
||||
RealFFTf1x(buffer, mEffectEqualization->hFFT.get());
|
||||
|
||||
// Apply filter
|
||||
// DC component is purely real
|
||||
|
@ -721,8 +720,8 @@ void EffectEqualization48x::Filter1x(size_t len,
|
|||
scratchBuffer[1] = buffer[1] * filterFuncR;
|
||||
|
||||
// Inverse FFT and normalization
|
||||
InverseRealFFTf1x(scratchBuffer, mEffectEqualization->hFFT);
|
||||
ReorderToTime1x(mEffectEqualization->hFFT, scratchBuffer, buffer);
|
||||
InverseRealFFTf1x(scratchBuffer, mEffectEqualization->hFFT.get());
|
||||
ReorderToTime1x(mEffectEqualization->hFFT.get(), scratchBuffer, buffer);
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
if(singleProcessLength && !bBreakLoop) {
|
||||
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, 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?mBlockSize:0], floatSample, singleProcessLength);
|
||||
}
|
||||
|
@ -965,8 +964,8 @@ bool EffectEqualization48x::ProcessOne1x4xThreaded(int count, WaveTrack * t,
|
|||
mDataMutex.Unlock(); // Get back in line for data
|
||||
}
|
||||
if(singleProcessLength && !bBreakLoop) {
|
||||
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
ProcessBuffer(mBigBuffer.get(), mBigBuffer.get(), singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
}
|
||||
output->Flush();
|
||||
|
@ -981,7 +980,7 @@ void EffectEqualization48x::Filter4x(size_t len,
|
|||
int i;
|
||||
__m128 real128, imag128;
|
||||
// Apply FFT
|
||||
RealFFTf4x(buffer, mEffectEqualization->hFFT);
|
||||
RealFFTf4x(buffer, mEffectEqualization->hFFT.get());
|
||||
|
||||
// Apply filter
|
||||
// DC component is purely real
|
||||
|
@ -1015,8 +1014,8 @@ void EffectEqualization48x::Filter4x(size_t len,
|
|||
localFFTBuffer[1] = _mm_mul_ps(localBuffer[1], filterFuncR);
|
||||
|
||||
// Inverse FFT and normalization
|
||||
InverseRealFFTf4x(scratchBuffer, mEffectEqualization->hFFT);
|
||||
ReorderToTime4x(mEffectEqualization->hFFT, scratchBuffer, buffer);
|
||||
InverseRealFFTf4x(scratchBuffer, mEffectEqualization->hFFT.get());
|
||||
ReorderToTime4x(mEffectEqualization->hFFT.get(), scratchBuffer, buffer);
|
||||
}
|
||||
|
||||
#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)));
|
||||
}
|
||||
if(singleProcessLength && !bBreakLoop) {
|
||||
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
ProcessBuffer(mBigBuffer.get(), mBigBuffer.get(), singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
}
|
||||
output->Flush();
|
||||
|
@ -1262,8 +1261,8 @@ bool EffectEqualization48x::ProcessOne8xThreaded(int count, WaveTrack * t,
|
|||
mDataMutex.Unlock(); // Get back in line for data
|
||||
}
|
||||
if(singleProcessLength && !bBreakLoop) {
|
||||
t->Get((samplePtr)mBigBuffer, floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
ProcessBuffer(mBigBuffer, mBigBuffer, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
t->Get((samplePtr)mBigBuffer.get(), floatSample, currentSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
ProcessBuffer(mBigBuffer.get(), mBigBuffer.get(), singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
output->Append((samplePtr)&mBigBuffer[mBlockSize], floatSample, singleProcessLength+mBlockSize+(mFilterSize>>1));
|
||||
}
|
||||
output->Flush();
|
||||
|
|
|
@ -32,6 +32,11 @@ Intrinsics (SSE/AVX) and Threaded Equalization
|
|||
#define MATH_FUNCTION_AVX 16
|
||||
#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
|
||||
enum EQBufferStatus
|
||||
{
|
||||
|
@ -156,7 +161,7 @@ private:
|
|||
size_t mBlocksPerBuffer;
|
||||
size_t mScratchBufferSize;
|
||||
size_t mSubBufferSize;
|
||||
float *mBigBuffer;
|
||||
simd_floats mBigBuffer;
|
||||
ArrayOf<BufferInfo> mBufferInfo;
|
||||
wxMutex mDataMutex;
|
||||
ArrayOf<EQWorker> mEQWorkers;
|
||||
|
|
|
@ -640,7 +640,6 @@ bool EffectNoiseReduction::Process()
|
|||
|
||||
EffectNoiseReduction::Worker::~Worker()
|
||||
{
|
||||
EndFFT(hFFT);
|
||||
}
|
||||
|
||||
bool EffectNoiseReduction::Worker::Process
|
||||
|
@ -727,7 +726,7 @@ EffectNoiseReduction::Worker::Worker
|
|||
, mSampleRate(sampleRate)
|
||||
|
||||
, mWindowSize(settings.WindowSize())
|
||||
, hFFT(InitializeFFT(mWindowSize))
|
||||
, hFFT(GetFFT(mWindowSize))
|
||||
, mFFTBuffer(mWindowSize)
|
||||
, mInWaveBuffer(mWindowSize)
|
||||
, mOutOverlapBuffer(mWindowSize)
|
||||
|
@ -945,7 +944,7 @@ void EffectNoiseReduction::Worker::FillFirstHistoryWindow()
|
|||
mFFTBuffer[ii] = mInWaveBuffer[ii] * mInWindow[ii];
|
||||
else
|
||||
memmove(&mFFTBuffer[0], &mInWaveBuffer[0], mWindowSize * sizeof(float));
|
||||
RealFFTf(&mFFTBuffer[0], hFFT);
|
||||
RealFFTf(&mFFTBuffer[0], hFFT.get());
|
||||
|
||||
Record &record = *mQueue[0];
|
||||
|
||||
|
@ -1243,7 +1242,7 @@ void EffectNoiseReduction::Worker::ReduceNoise
|
|||
}
|
||||
|
||||
// Invert the FFT into the output buffer
|
||||
InverseRealFFTf(&mFFTBuffer[0], hFFT);
|
||||
InverseRealFFTf(&mFFTBuffer[0], hFFT.get());
|
||||
|
||||
// Overlap-add
|
||||
if (mOutWindow.size() > 0) {
|
||||
|
|
|
@ -288,7 +288,7 @@ void EffectNoiseRemoval::Initialize()
|
|||
mImagFFTs.reinit(mHistoryLen, mSpectrumSize);
|
||||
|
||||
// Initialize the FFT
|
||||
hFFT = InitializeFFT(mWindowSize);
|
||||
hFFT = GetFFT(mWindowSize);
|
||||
|
||||
mFFTBuffer.reinit(mWindowSize);
|
||||
mInWaveBuffer.reinit(mWindowSize);
|
||||
|
@ -307,7 +307,7 @@ void EffectNoiseRemoval::Initialize()
|
|||
|
||||
void EffectNoiseRemoval::Cleanup()
|
||||
{
|
||||
EndFFT(hFFT);
|
||||
hFFT.reset();
|
||||
|
||||
if (mDoProfile) {
|
||||
ApplyFreqSmoothing(mNoiseThreshold.get());
|
||||
|
@ -374,8 +374,8 @@ void EffectNoiseRemoval::FillFirstHistoryWindow()
|
|||
{
|
||||
for(size_t i = 0; i < mWindowSize; i++)
|
||||
mFFTBuffer[i] = mInWaveBuffer[i];
|
||||
RealFFTf(mFFTBuffer.get(), hFFT);
|
||||
for(size_t i = 1; i < (mSpectrumSize-1); i++) {
|
||||
RealFFTf(mFFTBuffer.get(), hFFT.get());
|
||||
for(size_t i = 1; i + 1 < mSpectrumSize; i++) {
|
||||
mRealFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i] ];
|
||||
mImagFFTs[0][i] = mFFTBuffer[hFFT->BitReversed[i]+1];
|
||||
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];
|
||||
|
||||
// Invert the FFT into the output buffer
|
||||
InverseRealFFTf(mFFTBuffer.get(), hFFT);
|
||||
InverseRealFFTf(mFFTBuffer.get(), hFFT.get());
|
||||
|
||||
// Overlap-add
|
||||
for(size_t j = 0; j < (mSpectrumSize-1); j++) {
|
||||
|
|
|
@ -78,8 +78,8 @@ FactoryPresets[] =
|
|||
struct Reverb_priv_t
|
||||
{
|
||||
reverb_t reverb;
|
||||
float *dry;
|
||||
float *wet[2];
|
||||
float *dry {};
|
||||
float *wet[2] { {}, {} };
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -171,7 +171,7 @@ bool EffectReverb::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelName
|
|||
mNumChans = 2;
|
||||
}
|
||||
|
||||
mP = (Reverb_priv_t *) calloc(sizeof(*mP), mNumChans);
|
||||
mP.reinit(mNumChans, true);
|
||||
|
||||
for (int i = 0; i < mNumChans; i++)
|
||||
{
|
||||
|
@ -194,12 +194,7 @@ bool EffectReverb::ProcessInitialize(sampleCount WXUNUSED(totalLen), ChannelName
|
|||
|
||||
bool EffectReverb::ProcessFinalize()
|
||||
{
|
||||
for (int i = 0; i < mNumChans; i++)
|
||||
{
|
||||
reverb_delete(&mP[i].reverb);
|
||||
}
|
||||
|
||||
free(mP);
|
||||
mP.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ private:
|
|||
|
||||
private:
|
||||
unsigned mNumChans {};
|
||||
Reverb_priv_t *mP;
|
||||
ArrayOf<Reverb_priv_t> mP;
|
||||
|
||||
Params mParams;
|
||||
|
||||
|
|
|
@ -29,16 +29,15 @@ using std::max;
|
|||
#define FIFO_SIZE_T size_t
|
||||
#define FIFO_MIN 0x4000
|
||||
#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 filter_advance(p) if (--(p)->ptr < (p)->buffer) (p)->ptr += (p)->size
|
||||
#define filter_delete(p) free((p)->buffer)
|
||||
#define lsx_zalloc(var, n) (var.reinit(n, true), var.get())
|
||||
#define filter_advance(p) if (--(p)->ptr < (p)->buffer.get()) (p)->ptr += (p)->size
|
||||
|
||||
typedef struct {
|
||||
char * data;
|
||||
size_t allocation; /* Number of bytes allocated for data. */
|
||||
size_t item_size; /* Size of each item in data */
|
||||
size_t begin; /* Offset of the first byte to read. */
|
||||
size_t end; /* 1 + Offset of the last byte byte to read. */
|
||||
ArrayOf<char> data;
|
||||
size_t allocation {}; /* Number of bytes allocated for data. */
|
||||
size_t item_size {}; /* Size of each item in data */
|
||||
size_t begin {}; /* Offset of the first byte to read. */
|
||||
size_t end {}; /* 1 + Offset of the last byte byte to read. */
|
||||
} fifo_t;
|
||||
|
||||
static void fifo_clear(fifo_t * f)
|
||||
|
@ -55,19 +54,19 @@ static void * fifo_reserve(fifo_t * f, FIFO_SIZE_T n)
|
|||
|
||||
while (1) {
|
||||
if (f->end + n <= f->allocation) {
|
||||
void *p = f->data + f->end;
|
||||
void *p = f->data.get() + f->end;
|
||||
|
||||
f->end += n;
|
||||
return p;
|
||||
}
|
||||
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->begin = 0;
|
||||
continue;
|
||||
}
|
||||
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)
|
||||
{
|
||||
char * ret = f->data + f->begin;
|
||||
char * ret = f->data.get() + f->begin;
|
||||
n *= f->item_size;
|
||||
if (n > (FIFO_SIZE_T)(f->end - f->begin))
|
||||
return NULL;
|
||||
|
@ -91,22 +90,18 @@ static void * fifo_read(fifo_t * f, FIFO_SIZE_T n, void * data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void fifo_delete(fifo_t * f)
|
||||
{
|
||||
free(f->data);
|
||||
}
|
||||
|
||||
static void fifo_create(fifo_t * f, FIFO_SIZE_T item_size)
|
||||
{
|
||||
f->item_size = item_size;
|
||||
f->allocation = FIFO_MIN;
|
||||
f->data = (char *)malloc(f->allocation);
|
||||
f->data.reinit(f->allocation);
|
||||
fifo_clear(f);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
float * buffer, * ptr;
|
||||
ArrayOf<float> buffer;
|
||||
float * ptr;
|
||||
float store;
|
||||
} 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 {
|
||||
float feedback;
|
||||
float hf_damping;
|
||||
float gain;
|
||||
fifo_t input_fifo;
|
||||
float feedback {};
|
||||
float hf_damping {};
|
||||
float gain {};
|
||||
fifo_t input_fifo {};
|
||||
filter_array_t chan[2];
|
||||
float * out[2];
|
||||
ArrayOf<float> out[2];
|
||||
} reverb_t;
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,38 +33,29 @@ public:
|
|||
ResampleBuf()
|
||||
{
|
||||
processed = 0;
|
||||
buf = NULL;
|
||||
leftBuffer = NULL;
|
||||
rightBuffer = NULL;
|
||||
|
||||
SBSMSBuf = NULL;
|
||||
outputLeftTrack = NULL;
|
||||
outputRightTrack = NULL;
|
||||
}
|
||||
|
||||
~ResampleBuf()
|
||||
{
|
||||
if(buf) free(buf);
|
||||
if(leftBuffer) free(leftBuffer);
|
||||
if(rightBuffer) free(rightBuffer);
|
||||
if(SBSMSBuf) free(SBSMSBuf);
|
||||
}
|
||||
|
||||
bool bPitch;
|
||||
audio *buf;
|
||||
ArrayOf<audio> buf;
|
||||
double ratio;
|
||||
sampleCount processed;
|
||||
size_t blockSize;
|
||||
long SBSMSBlockSize;
|
||||
sampleCount offset;
|
||||
sampleCount end;
|
||||
float *leftBuffer;
|
||||
float *rightBuffer;
|
||||
ArrayOf<float> leftBuffer;
|
||||
ArrayOf<float> rightBuffer;
|
||||
WaveTrack *leftTrack;
|
||||
WaveTrack *rightTrack;
|
||||
std::unique_ptr<SBSMS> sbsms;
|
||||
std::unique_ptr<SBSMSInterface> iface;
|
||||
audio *SBSMSBuf;
|
||||
ArrayOf<audio> SBSMSBuf;
|
||||
|
||||
// Not required by callbacks, but makes for easier cleanup
|
||||
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.
|
||||
r->leftTrack->Get((samplePtr)(r->leftBuffer), floatSample, r->offset, blockSize);
|
||||
r->rightTrack->Get((samplePtr)(r->rightBuffer), floatSample, r->offset, blockSize);
|
||||
r->leftTrack->Get((samplePtr)(r->leftBuffer.get()), floatSample, r->offset, blockSize);
|
||||
r->rightTrack->Get((samplePtr)(r->rightBuffer.get()), floatSample, r->offset, blockSize);
|
||||
|
||||
// convert to sbsms audio format
|
||||
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];
|
||||
}
|
||||
|
||||
data->buf = r->buf;
|
||||
data->buf = r->buf.get();
|
||||
data->size = blockSize;
|
||||
if(r->bPitch) {
|
||||
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)
|
||||
{
|
||||
ResampleBuf *r = (ResampleBuf*) cb_data;
|
||||
auto count = r->sbsms->read(r->iface.get(), r->SBSMSBuf, r->SBSMSBlockSize);
|
||||
data->buf = r->SBSMSBuf;
|
||||
auto count = r->sbsms->read(r->iface.get(), r->SBSMSBuf.get(), r->SBSMSBlockSize);
|
||||
data->buf = r->SBSMSBuf.get();
|
||||
data->size = count;
|
||||
data->ratio0 = 1.0 / r->ratio;
|
||||
data->ratio1 = 1.0 / r->ratio;
|
||||
|
@ -285,11 +276,11 @@ bool EffectSBSMS::Process()
|
|||
ResampleBuf rb;
|
||||
auto maxBlockSize = leftTrack->GetMaxBlockSize();
|
||||
rb.blockSize = maxBlockSize;
|
||||
rb.buf = (audio*)calloc(rb.blockSize,sizeof(audio));
|
||||
rb.buf.reinit(rb.blockSize, true);
|
||||
rb.leftTrack = leftTrack;
|
||||
rb.rightTrack = rightTrack?rightTrack:leftTrack;
|
||||
rb.leftBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rb.rightBuffer = (float*)calloc(maxBlockSize,sizeof(float));
|
||||
rb.leftBuffer.reinit(maxBlockSize, true);
|
||||
rb.rightBuffer.reinit(maxBlockSize, true);
|
||||
|
||||
// Samples in selection
|
||||
auto samplesIn = end - start;
|
||||
|
@ -325,7 +316,7 @@ bool EffectSBSMS::Process()
|
|||
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.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
|
||||
decltype(start) processPresamples = rb.quality->getMaxPresamples();
|
||||
|
|
|
@ -277,7 +277,8 @@ void AUControl::CreateCocoa()
|
|||
return;
|
||||
}
|
||||
|
||||
AudioUnitCocoaViewInfo *viewInfo = (AudioUnitCocoaViewInfo *) malloc(dataSize);
|
||||
ArrayOf<char> buffer{ dataSize };
|
||||
auto viewInfo = (AudioUnitCocoaViewInfo *) buffer.get();
|
||||
if (viewInfo == NULL)
|
||||
{
|
||||
return;
|
||||
|
@ -331,8 +332,6 @@ void AUControl::CreateCocoa()
|
|||
}
|
||||
}
|
||||
|
||||
free(viewInfo);
|
||||
|
||||
if (!mView)
|
||||
{
|
||||
return;
|
||||
|
@ -474,7 +473,8 @@ void AUControl::CreateCarbon()
|
|||
return;
|
||||
}
|
||||
|
||||
AudioComponentDescription *compList = (AudioComponentDescription *) malloc(dataSize);
|
||||
ArrayOf<char> buffer{ dataSize };
|
||||
auto compList = (AudioComponentDescription *) buffer.get();
|
||||
if (compList == NULL)
|
||||
{
|
||||
return;
|
||||
|
@ -488,11 +488,7 @@ void AUControl::CreateCarbon()
|
|||
compList,
|
||||
&dataSize);
|
||||
if (result != noErr)
|
||||
{
|
||||
free(compList);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the component
|
||||
AudioComponent comp = AudioComponentFindNext(NULL, &compList[0]);
|
||||
|
@ -500,9 +496,6 @@ void AUControl::CreateCarbon()
|
|||
// Try to create an instance
|
||||
result = AudioComponentInstanceNew(comp, &mInstance);
|
||||
|
||||
// Done with the list
|
||||
free(compList);
|
||||
|
||||
if (result != noErr)
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -2187,7 +2187,8 @@ void AudioUnitEffect::GetChannelCounts()
|
|||
return;
|
||||
}
|
||||
|
||||
AUChannelInfo *info = (AUChannelInfo *) malloc(dataSize);
|
||||
ArrayOf<char> buffer{ dataSize };
|
||||
auto info = (AUChannelInfo *) buffer.get();
|
||||
|
||||
// Retrieve the channel info
|
||||
result = AudioUnitGetProperty(mUnit,
|
||||
|
@ -2202,7 +2203,6 @@ void AudioUnitEffect::GetChannelCounts()
|
|||
mAudioIns = 2;
|
||||
mAudioOuts = 2;
|
||||
|
||||
free(info);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -316,11 +316,6 @@ LV2Effect::LV2Effect(const LilvPlugin *plug)
|
|||
|
||||
mDialog = NULL;
|
||||
|
||||
mURIMap = NULL;
|
||||
mNumURIMap = 0;
|
||||
mOptions = NULL;
|
||||
mNumOptions = 0;
|
||||
|
||||
mIdleFeature = NULL;
|
||||
mOptionsInterface = NULL;
|
||||
|
||||
|
@ -329,19 +324,6 @@ LV2Effect::LV2Effect(const LilvPlugin *plug)
|
|||
|
||||
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__noUserResize, 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_URID__map, &mURIDMapFeature);
|
||||
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)
|
||||
{
|
||||
int ndx = mNumOptions;
|
||||
int ndx = mOptions.size();
|
||||
|
||||
mNumOptions += 1;
|
||||
mOptions = (LV2_Options_Option *) realloc(mOptions, mNumOptions * sizeof(LV2_Options_Option));
|
||||
mOptions.resize(1 + mOptions.size());
|
||||
memset(&mOptions[ndx], 0, sizeof(mOptions[ndx]));
|
||||
|
||||
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)
|
||||
{
|
||||
mFeatures.resize(mFeatures.size() + 1);
|
||||
|
||||
auto &pFeature = mFeatures.back();
|
||||
size_t ndx = mFeatures.size();
|
||||
mFeatures.resize(1 + mFeatures.size());
|
||||
|
||||
if (uri != NULL)
|
||||
{
|
||||
pFeature = make_movable<LV2_Feature>();
|
||||
pFeature->URI = uri;
|
||||
pFeature->data = data;
|
||||
mFeatures[ndx].reset( safenew LV2_Feature );
|
||||
mFeatures[ndx]->URI = uri;
|
||||
mFeatures[ndx]->data = data;
|
||||
}
|
||||
|
||||
mFeaturePtrs.push_back(pFeature.get());
|
||||
return pFeature.get();
|
||||
return mFeatures[ndx].get();
|
||||
}
|
||||
|
||||
LilvInstance *LV2Effect::InitInstance(float sampleRate)
|
||||
{
|
||||
LilvInstance *handle = lilv_plugin_instantiate(mPlug,
|
||||
sampleRate,
|
||||
mFeaturePtrs.data());
|
||||
LilvInstance *handle = lilv_plugin_instantiate(
|
||||
mPlug, sampleRate,
|
||||
reinterpret_cast<const LV2_Feature *const *>(mFeatures.data()));
|
||||
if (!handle)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -1478,7 +1457,7 @@ bool LV2Effect::BuildFancy()
|
|||
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_binary_uri(ui))),
|
||||
mFeaturePtrs.data());
|
||||
reinterpret_cast<const LV2_Feature *const *>(mFeatures.data()));
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
mNumURIMap += 1;
|
||||
mURIMap = (char **) realloc(mURIMap, mNumURIMap * sizeof(char*));
|
||||
mURIMap[mNumURIMap - 1] = strdup(uri);
|
||||
mURIMap.resize(1 + mURIMap.size());
|
||||
mURIMap[ndx].reset( strdup(uri) );
|
||||
|
||||
return mNumURIMap;
|
||||
return ndx + 1;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#include "../../MemoryX.h"
|
||||
#include <vector>
|
||||
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/dynarray.h>
|
||||
|
@ -289,8 +288,7 @@ private:
|
|||
|
||||
bool mUseGUI;
|
||||
|
||||
char **mURIMap;
|
||||
int mNumURIMap;
|
||||
std::vector< movable_ptr_with_deleter<char, freer> > mURIMap;
|
||||
|
||||
LV2_URI_Map_Feature mUriMapFeature;
|
||||
LV2_URID_Map mURIDMapFeature;
|
||||
|
@ -302,11 +300,9 @@ private:
|
|||
size_t mSampleRateOption;
|
||||
|
||||
LV2_Options_Interface *mOptionsInterface;
|
||||
LV2_Options_Option *mOptions;
|
||||
int mNumOptions;
|
||||
std::vector<LV2_Options_Option> mOptions;
|
||||
|
||||
std::vector<movable_ptr<LV2_Feature>> mFeatures;
|
||||
std::vector<LV2_Feature*> mFeaturePtrs;
|
||||
|
||||
LV2_Feature *mInstanceAccessFeature;
|
||||
LV2_Feature *mParentFeature;
|
||||
|
|
|
@ -240,7 +240,7 @@ wxWindow *ExportPlugin::OptionsCreate(wxWindow *parent, int WXUNUSED(format))
|
|||
std::unique_ptr<Mixer> ExportPlugin::CreateMixer(const WaveTrackConstArray &inputTracks,
|
||||
const TimeTrack *timeTrack,
|
||||
double startTime, double stopTime,
|
||||
unsigned numOutChannels, int outBufferSize, bool outInterleaved,
|
||||
unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
|
||||
double outRate, sampleFormat outFormat,
|
||||
bool highQuality, MixerSpec *mixerSpec)
|
||||
{
|
||||
|
|
|
@ -123,7 +123,7 @@ protected:
|
|||
std::unique_ptr<Mixer> CreateMixer(const WaveTrackConstArray &inputTracks,
|
||||
const TimeTrack *timeTrack,
|
||||
double startTime, double stopTime,
|
||||
unsigned numOutChannels, int outBufferSize, bool outInterleaved,
|
||||
unsigned numOutChannels, size_t outBufferSize, bool outInterleaved,
|
||||
double outRate, sampleFormat outFormat,
|
||||
bool highQuality = true, MixerSpec *mixerSpec = NULL);
|
||||
|
||||
|
|
|
@ -857,7 +857,7 @@ ProgressResult ExportFFmpeg::Export(AudacityProject *project,
|
|||
if (!ret)
|
||||
return ProgressResult::Cancelled;
|
||||
|
||||
int pcmBufferSize = 1024;
|
||||
size_t pcmBufferSize = 1024;
|
||||
const WaveTrackConstArray waveTracks =
|
||||
tracks->GetWaveTrackConstArray(selectionOnly, false);
|
||||
auto mixer = CreateMixer(waveTracks,
|
||||
|
|
|
@ -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
|
||||
{
|
||||
public:
|
||||
|
@ -196,7 +204,7 @@ private:
|
|||
|
||||
bool GetMetadata(AudacityProject *project, const Tags *tags);
|
||||
|
||||
FLAC__StreamMetadata *mMetadata;
|
||||
FLAC__StreamMetadataHandle mMetadata;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -248,7 +256,10 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -299,9 +310,7 @@ ProgressResult ExportFLAC::Export(AudacityProject *project,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (mMetadata) {
|
||||
::FLAC__metadata_object_delete(mMetadata);
|
||||
}
|
||||
mMetadata.reset();
|
||||
|
||||
const WaveTrackConstArray waveTracks =
|
||||
tracks->GetWaveTrackConstArray(selectionOnly, false);
|
||||
|
@ -367,7 +376,7 @@ bool ExportFLAC::GetMetadata(AudacityProject *project, const Tags *tags)
|
|||
if (tags == NULL)
|
||||
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;
|
||||
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),
|
||||
v.mb_str(wxConvUTF8));
|
||||
::FLAC__metadata_object_vorbiscomment_append_comment(mMetadata,
|
||||
::FLAC__metadata_object_vorbiscomment_append_comment(mMetadata.get(),
|
||||
entry.get_entry(),
|
||||
true);
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ public:
|
|||
|
||||
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
|
||||
void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name);
|
||||
#endif
|
||||
|
@ -242,15 +242,15 @@ ProgressResult ExportMP2::Export(AudacityProject *project,
|
|||
return ProgressResult::Cancelled;
|
||||
}
|
||||
|
||||
char *id3buffer = NULL;
|
||||
ArrayOf<char> id3buffer;
|
||||
int id3len;
|
||||
bool endOfFile;
|
||||
id3len = AddTags(project, &id3buffer, &endOfFile, metadata);
|
||||
id3len = AddTags(project, id3buffer, &endOfFile, metadata);
|
||||
if (id3len && !endOfFile)
|
||||
outFile.Write(id3buffer, id3len);
|
||||
outFile.Write(id3buffer.get(), id3len);
|
||||
|
||||
// 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
|
||||
|
||||
// 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 */
|
||||
|
||||
if (id3len && endOfFile)
|
||||
outFile.Write(id3buffer, id3len);
|
||||
|
||||
if (id3buffer) {
|
||||
free(id3buffer);
|
||||
}
|
||||
outFile.Write(id3buffer.get(), id3len);
|
||||
|
||||
/* Close file */
|
||||
|
||||
|
@ -326,11 +322,16 @@ wxWindow *ExportMP2::OptionsCreate(wxWindow *parent, int 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
|
||||
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
|
||||
struct id3_tag *tp = id3_tag_new();
|
||||
id3_tag_holder tp { id3_tag_new() };
|
||||
|
||||
for (const auto &pair : tags->GetRange()) {
|
||||
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) {
|
||||
// LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
|
||||
// so we add old one as well.
|
||||
AddFrame(tp, n, v, "TYER");
|
||||
AddFrame(tp.get(), n, v, "TYER");
|
||||
name = ID3_FRAME_YEAR;
|
||||
}
|
||||
else if (n.CmpNoCase(TAG_GENRE) == 0) {
|
||||
|
@ -362,7 +363,7 @@ int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool
|
|||
name = ID3_FRAME_TRACK;
|
||||
}
|
||||
|
||||
AddFrame(tp, n, v, name);
|
||||
AddFrame(tp.get(), n, v, name);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
len = id3_tag_render(tp, 0);
|
||||
*buffer = (char *)malloc(len);
|
||||
len = id3_tag_render(tp, (id3_byte_t *)*buffer);
|
||||
len = id3_tag_render(tp.get(), 0);
|
||||
buffer.reinit(len);
|
||||
len = id3_tag_render(tp.get(), (id3_byte_t *)buffer.get());
|
||||
|
||||
id3_tag_delete(tp);
|
||||
|
||||
return len;
|
||||
#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_ucs4_t *ucs4 =
|
||||
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8));
|
||||
MallocString<id3_ucs4_t> ucs4 {
|
||||
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
|
||||
|
||||
if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
|
||||
// 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.
|
||||
id3_field *f = id3_frame_field(frame, 1);
|
||||
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) {
|
||||
id3_field_setstring(id3_frame_field(frame, 2), ucs4);
|
||||
free(ucs4);
|
||||
id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1617,7 +1617,7 @@ private:
|
|||
int FindValue(CHOICES *choices, int cnt, int needle, int def);
|
||||
wxString FindName(CHOICES *choices, int cnt, int needle);
|
||||
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
|
||||
void AddFrame(struct id3_tag *tp, const wxString & n, const wxString & v, const char *name);
|
||||
#endif
|
||||
|
@ -1796,12 +1796,12 @@ ProgressResult ExportMP3::Export(AudacityProject *project,
|
|||
return ProgressResult::Cancelled;
|
||||
}
|
||||
|
||||
char *id3buffer = NULL;
|
||||
ArrayOf<char> id3buffer;
|
||||
int id3len;
|
||||
bool endOfFile;
|
||||
id3len = AddTags(project, &id3buffer, &endOfFile, metadata);
|
||||
id3len = AddTags(project, id3buffer, &endOfFile, metadata);
|
||||
if (id3len && !endOfFile) {
|
||||
outFile.Write(id3buffer, id3len);
|
||||
outFile.Write(id3buffer.get(), id3len);
|
||||
}
|
||||
|
||||
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
|
||||
if (id3len && endOfFile) {
|
||||
outFile.Write(id3buffer, id3len);
|
||||
}
|
||||
|
||||
if (id3buffer) {
|
||||
free(id3buffer);
|
||||
outFile.Write(id3buffer.get(), id3len);
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
struct id3_tag *tp = id3_tag_new();
|
||||
id3_tag_holder tp { id3_tag_new() };
|
||||
|
||||
for (const auto &pair : tags->GetRange()) {
|
||||
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) {
|
||||
// LLL: Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
|
||||
// so we add old one as well.
|
||||
AddFrame(tp, n, v, "TYER");
|
||||
AddFrame(tp.get(), n, v, "TYER");
|
||||
name = ID3_FRAME_YEAR;
|
||||
}
|
||||
else if (n.CmpNoCase(TAG_GENRE) == 0) {
|
||||
|
@ -2044,7 +2045,7 @@ int ExportMP3::AddTags(AudacityProject *WXUNUSED(project), char **buffer, bool *
|
|||
name = ID3_FRAME_TRACK;
|
||||
}
|
||||
|
||||
AddFrame(tp, n, v, name);
|
||||
AddFrame(tp.get(), n, v, name);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
len = id3_tag_render(tp, 0);
|
||||
*buffer = (char *)malloc(len);
|
||||
len = id3_tag_render(tp, (id3_byte_t *)*buffer);
|
||||
|
||||
id3_tag_delete(tp);
|
||||
len = id3_tag_render(tp.get(), 0);
|
||||
buffer.reinit(len);
|
||||
len = id3_tag_render(tp.get(), (id3_byte_t *)buffer.get());
|
||||
|
||||
return len;
|
||||
#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_ucs4_t *ucs4 =
|
||||
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8));
|
||||
MallocString<id3_ucs4_t> ucs4{
|
||||
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
|
||||
|
||||
if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
|
||||
// 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
|
||||
// way of clearing the field, so do it directly.
|
||||
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);
|
||||
memset(f2->immediate.value, 0, sizeof(f2->immediate.value));
|
||||
id3_tag_attachframe(tp, frame2);
|
||||
// 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) {
|
||||
id3_field_setstring(id3_frame_field(frame, 2), ucs4);
|
||||
free(ucs4);
|
||||
id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -121,7 +121,7 @@ bool ExportOGGOptions::TransferDataFromWindow()
|
|||
// ExportOGG
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define SAMPLES_PER_RUN 8192
|
||||
#define SAMPLES_PER_RUN 8192u
|
||||
|
||||
class ExportOGG final : public ExportPlugin
|
||||
{
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "../FileFormats.h"
|
||||
#include "../Internat.h"
|
||||
#include "../MemoryX.h"
|
||||
#include "../Mix.h"
|
||||
#include "../Prefs.h"
|
||||
#include "../Project.h"
|
||||
|
@ -328,7 +329,7 @@ public:
|
|||
|
||||
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);
|
||||
void AddID3Chunk(wxString fName, const Tags *tags, int sf_format);
|
||||
|
||||
|
@ -472,7 +473,7 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
|
|||
else
|
||||
format = int16Sample;
|
||||
|
||||
int maxBlockLen = 44100 * 5;
|
||||
size_t maxBlockLen = 44100 * 5;
|
||||
|
||||
const WaveTrackConstArray waveTracks =
|
||||
tracks->GetWaveTrackConstArray(selectionOnly, false);
|
||||
|
@ -538,7 +539,7 @@ ProgressResult ExportPCM::Export(AudacityProject *project,
|
|||
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;
|
||||
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
|
||||
size_t sz = wxStr.length();
|
||||
if(sz == 0)
|
||||
return NULL;
|
||||
// Size for secure malloc in case of local wide char usage
|
||||
return {};
|
||||
// Size for secure allocation in case of local wide char usage
|
||||
size_t sr = (sz+4) * 2;
|
||||
|
||||
char *pDest = (char *)malloc(sr);
|
||||
ArrayOf<char> pDest{ sr, true };
|
||||
if (!pDest)
|
||||
return NULL;
|
||||
char *pSrc = (char *)malloc(sr);
|
||||
return {};
|
||||
ArrayOf<char> pSrc{ sr, true };
|
||||
if (!pSrc)
|
||||
{
|
||||
free(pDest);
|
||||
return NULL;
|
||||
}
|
||||
memset(pDest, 0, sr);
|
||||
memset(pSrc, 0, sr);
|
||||
return {};
|
||||
|
||||
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())
|
||||
strncpy(pSrc, wxStr.mb_str(), sz);
|
||||
else {
|
||||
free(pDest);
|
||||
free(pSrc);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(pSrc.get(), wxStr.mb_str(), sz);
|
||||
else
|
||||
return {};
|
||||
|
||||
char *pD = pDest;
|
||||
char *pS = pSrc;
|
||||
char *pD = pDest.get();
|
||||
char *pS = pSrc.get();
|
||||
unsigned char c;
|
||||
|
||||
// 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';
|
||||
|
||||
free(pSrc);
|
||||
|
||||
if(b_aiff) {
|
||||
int len = (int)strlen(pDest);
|
||||
int len = (int)strlen(pDest.get());
|
||||
if((len % 2) != 0) {
|
||||
// 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)
|
||||
{
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_TITLE, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_TITLE, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_ALBUM, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_ALBUM, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_ARTIST, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_ARTIST, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_COMMENT, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_COMMENT, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_DATE, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_DATE, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_GENRE, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_GENRE, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_COPYRIGHT, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_COPYRIGHT, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_SOFTWARE, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_SOFTWARE, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
sf_set_string(sf, SF_STR_TRACKNUMBER, ascii7Str);
|
||||
free(ascii7Str);
|
||||
sf_set_string(sf, SF_STR_TRACKNUMBER, ascii7Str.get());
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
#ifdef USE_LIBID3TAG
|
||||
struct id3_tag *tp = id3_tag_new();
|
||||
id3_tag_holder tp { id3_tag_new() };
|
||||
|
||||
for (const auto &pair : tags->GetRange()) {
|
||||
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_ucs4_t *ucs4 =
|
||||
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8));
|
||||
MallocString<id3_ucs4_t> ucs4{
|
||||
id3_utf8_ucs4duplicate((id3_utf8_t *) (const char *) v.mb_str(wxConvUTF8)) };
|
||||
|
||||
if (strcmp(name, ID3_FRAME_COMMENT) == 0) {
|
||||
// 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.
|
||||
id3_field *f = id3_frame_field(frame, 1);
|
||||
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) {
|
||||
id3_field_setstring(id3_frame_field(frame, 2), ucs4);
|
||||
free(ucs4);
|
||||
id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
|
||||
|
||||
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 {
|
||||
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.get(), frame);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
len = id3_tag_render(tp, 0);
|
||||
if (len == 0) {
|
||||
id3_tag_delete(tp);
|
||||
len = id3_tag_render(tp.get(), 0);
|
||||
if (len == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((len % 2) != 0) len++; // Length must be even.
|
||||
id3_byte_t *buffer = (id3_byte_t *)malloc(len);
|
||||
if (buffer == NULL) {
|
||||
id3_tag_delete(tp);
|
||||
ArrayOf<id3_byte_t> buffer { len, true };
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
// Zero all locations, for ending odd UTF16 content
|
||||
// correctly, i.e., two '\0's at the end.
|
||||
memset(buffer, 0, len);
|
||||
|
||||
id3_tag_render(tp, buffer);
|
||||
|
||||
id3_tag_delete(tp);
|
||||
id3_tag_render(tp.get(), buffer.get());
|
||||
|
||||
wxFFile f(fName, wxT("r+b"));
|
||||
// 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(buffer, len);
|
||||
f.Write(buffer.get(), len);
|
||||
|
||||
sz = (wxUint32) f.Tell() - 8;
|
||||
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();
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -732,13 +732,10 @@ ProgressResult FFmpegImportFileHandle::WriteData(streamContext *sc)
|
|||
}
|
||||
|
||||
// Allocate the buffer to store audio.
|
||||
int 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;
|
||||
uint8_t **tmp = (uint8_t **) malloc(sizeof(uint8_t *) * nChannels);
|
||||
for (int chn = 0; chn < nChannels; chn++)
|
||||
{
|
||||
tmp[chn] = (uint8_t *) malloc(sc->m_osamplesize * (insamples / nChannels));
|
||||
}
|
||||
auto insamples = sc->m_decodedAudioSamplesValidSiz / sc->m_samplesize;
|
||||
size_t nChannels = std::min(sc->m_stream->codec->channels, sc->m_initialchannels);
|
||||
|
||||
ArraysOf<uint8_t> tmp{ nChannels, sc->m_osamplesize * (insamples / nChannels) };
|
||||
|
||||
// Separate the channels and convert input sample format to 16-bit
|
||||
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_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;
|
||||
|
||||
case AV_SAMPLE_FMT_S16:
|
||||
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;
|
||||
|
||||
case AV_SAMPLE_FMT_S32:
|
||||
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;
|
||||
|
||||
case AV_SAMPLE_FMT_FLT:
|
||||
case AV_SAMPLE_FMT_FLTP:
|
||||
((float *)tmp[chn])[index] = (float) *(float *)in;
|
||||
((float *)tmp[chn].get())[index] = (float) *(float *)in;
|
||||
break;
|
||||
|
||||
case AV_SAMPLE_FMT_DBL:
|
||||
case AV_SAMPLE_FMT_DBLP:
|
||||
((float *)tmp[chn])[index] = (float) *(double *)in;
|
||||
((float *)tmp[chn].get())[index] = (float) *(double *)in;
|
||||
break;
|
||||
|
||||
default:
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
@ -798,12 +790,9 @@ ProgressResult FFmpegImportFileHandle::WriteData(streamContext *sc)
|
|||
auto iter2 = iter->begin();
|
||||
for (int chn=0; chn < nChannels; ++iter2, ++chn)
|
||||
{
|
||||
iter2->get()->Append((samplePtr)tmp[chn],sc->m_osamplefmt,index);
|
||||
free(tmp[chn]);
|
||||
iter2->get()->Append((samplePtr)tmp[chn].get(), sc->m_osamplefmt, index);
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
|
||||
// Try to update the progress indicator (and see if user wants to cancel)
|
||||
auto updateResult = ProgressResult::Success;
|
||||
int64_t filesize = avio_size(mFormatContext->pb);
|
||||
|
|
|
@ -356,9 +356,8 @@ void MP3ImportFileHandle::ImportID3(Tags *tags)
|
|||
else if (frame->nfields == 3) {
|
||||
ustr = id3_field_getstring(&frame->fields[1]);
|
||||
if (ustr) {
|
||||
char *str = (char *)id3_ucs4_utf8duplicate(ustr);
|
||||
n = UTF8CTOWX(str);
|
||||
free(str);
|
||||
MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
|
||||
n = UTF8CTOWX(str.get());
|
||||
}
|
||||
|
||||
ustr = id3_field_getstring(&frame->fields[2]);
|
||||
|
@ -368,9 +367,8 @@ void MP3ImportFileHandle::ImportID3(Tags *tags)
|
|||
}
|
||||
|
||||
if (ustr) {
|
||||
char *str = (char *)id3_ucs4_utf8duplicate(ustr);
|
||||
v = UTF8CTOWX(str);
|
||||
free(str);
|
||||
MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
|
||||
v = UTF8CTOWX(str.get());
|
||||
}
|
||||
|
||||
if (!n.IsEmpty() && !v.IsEmpty()) {
|
||||
|
|
|
@ -324,6 +324,11 @@ How do you want to import the current file(s)?"), oldCopyPref == wxT("copy") ? _
|
|||
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,
|
||||
TrackHolders &outTracks,
|
||||
Tags *tags)
|
||||
|
@ -584,14 +589,17 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
continue;
|
||||
}
|
||||
|
||||
id3_byte_t *buffer = (id3_byte_t *)malloc(len);
|
||||
if (!buffer) {
|
||||
break;
|
||||
}
|
||||
|
||||
f.Read(buffer, len);
|
||||
struct id3_tag *tp = id3_tag_parse(buffer, len);
|
||||
free(buffer);
|
||||
id3_tag_holder tp;
|
||||
{
|
||||
ArrayOf<id3_byte_t> buffer{ len };
|
||||
if (!buffer) {
|
||||
break;
|
||||
}
|
||||
|
||||
f.Read(buffer.get(), len);
|
||||
tp.reset( id3_tag_parse(buffer.get(), len) );
|
||||
}
|
||||
|
||||
if (!tp) {
|
||||
break;
|
||||
|
@ -662,9 +670,8 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
else if (frame->nfields == 3) {
|
||||
ustr = id3_field_getstring(&frame->fields[1]);
|
||||
if (ustr) {
|
||||
char *str = (char *)id3_ucs4_utf8duplicate(ustr);
|
||||
n = UTF8CTOWX(str);
|
||||
free(str);
|
||||
MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
|
||||
n = UTF8CTOWX(str.get());
|
||||
}
|
||||
|
||||
ustr = id3_field_getstring(&frame->fields[2]);
|
||||
|
@ -674,9 +681,8 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
}
|
||||
|
||||
if (ustr) {
|
||||
char *str = (char *)id3_ucs4_utf8duplicate(ustr);
|
||||
v = UTF8CTOWX(str);
|
||||
free(str);
|
||||
MallocString<> str{ (char *)id3_ucs4_utf8duplicate(ustr) };
|
||||
v = UTF8CTOWX(str.get());
|
||||
}
|
||||
|
||||
if (!n.IsEmpty() && !v.IsEmpty()) {
|
||||
|
@ -692,7 +698,6 @@ ProgressResult PCMImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
}
|
||||
}
|
||||
|
||||
id3_tag_delete(tp);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -319,18 +319,22 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
format = floatSample;
|
||||
break;
|
||||
}
|
||||
|
||||
AudioBufferList *abl = (AudioBufferList *)
|
||||
calloc(1, offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * numchan));
|
||||
|
||||
std::unique_ptr<AudioBufferList, freer> abl
|
||||
{ static_cast<AudioBufferList *>
|
||||
(calloc(1, offsetof(AudioBufferList, mBuffers) +
|
||||
(sizeof(AudioBuffer) * numchan))) };
|
||||
abl->mNumberBuffers = numchan;
|
||||
|
||||
TrackHolders channels{ numchan };
|
||||
|
||||
|
||||
ArraysOf<unsigned char> holders{ numchan, sizeof(float) * bufsize };
|
||||
int c;
|
||||
for (c = 0; c < numchan; c++) {
|
||||
abl->mBuffers[c].mNumberChannels = 1;
|
||||
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]->SetRate(desc.mSampleRate);
|
||||
|
@ -352,7 +356,7 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
|
||||
err = MovieAudioExtractionFillBuffer(maer,
|
||||
&numFrames,
|
||||
abl,
|
||||
abl.get(),
|
||||
&flags);
|
||||
if (err != noErr) {
|
||||
wxMessageBox(_("Unable to get fill buffer"));
|
||||
|
@ -383,12 +387,7 @@ ProgressResult QTImportFileHandle::Import(TrackFactory *trackFactory,
|
|||
|
||||
outTracks.swap(channels);
|
||||
}
|
||||
|
||||
for (c = 0; c < numchan; c++) {
|
||||
free(abl->mBuffers[c].mData);
|
||||
}
|
||||
free(abl);
|
||||
|
||||
|
||||
//
|
||||
// Extract any metadata
|
||||
//
|
||||
|
@ -463,7 +462,6 @@ void QTImportFileHandle::AddMetadata(Tags *tags)
|
|||
continue;
|
||||
}
|
||||
|
||||
QTPropertyValuePtr outValPtr = nil;
|
||||
QTPropertyValueType outPropType;
|
||||
::ByteCount outPropValueSize;
|
||||
::ByteCount outPropValueSizeUsed = 0;
|
||||
|
@ -495,7 +493,7 @@ void QTImportFileHandle::AddMetadata(Tags *tags)
|
|||
}
|
||||
|
||||
// Alloc memory for it
|
||||
outValPtr = malloc(outPropValueSize);
|
||||
ArrayOf<char> outVals{ outPropValueSize };
|
||||
|
||||
// Retrieve the data
|
||||
err = QTMetaDataGetItemProperty(metaDataRef,
|
||||
|
@ -503,24 +501,22 @@ void QTImportFileHandle::AddMetadata(Tags *tags)
|
|||
kPropertyClass_MetaDataItem,
|
||||
kQTMetaDataItemPropertyID_Value,
|
||||
outPropValueSize,
|
||||
outValPtr,
|
||||
outVals.get(),
|
||||
&outPropValueSizeUsed);
|
||||
if (err != noErr) {
|
||||
free(outValPtr);
|
||||
if (err != noErr)
|
||||
continue;
|
||||
}
|
||||
|
||||
wxString v = wxT("");
|
||||
|
||||
switch (dataType)
|
||||
{
|
||||
case kQTMetaDataTypeUTF8:
|
||||
v = wxString((char *)outValPtr, wxConvUTF8);
|
||||
v = wxString(outVals.get(), wxConvUTF8);
|
||||
break;
|
||||
case kQTMetaDataTypeUTF16BE:
|
||||
{
|
||||
wxMBConvUTF16BE conv;
|
||||
v = wxString((char *)outValPtr, conv);
|
||||
v = wxString(outVals.get(), conv);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -528,8 +524,6 @@ void QTImportFileHandle::AddMetadata(Tags *tags)
|
|||
if (!v.IsEmpty()) {
|
||||
tags->SetTag(names[i].name, v);
|
||||
}
|
||||
|
||||
free(outValPtr);
|
||||
}
|
||||
|
||||
// we are done so release our metadata object
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
|
||||
**********************************************************************/
|
||||
|
||||
#include "../Audacity.h"
|
||||
#include "RawAudioGuess.h"
|
||||
#include "../MemoryX.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -31,10 +33,9 @@
|
|||
static FILE *g_raw_debug_file = NULL;
|
||||
#endif
|
||||
|
||||
static float AmpStat(float *data, int len)
|
||||
static float AmpStat(float *data, size_t len)
|
||||
{
|
||||
float sum, sumofsquares, avg, variance, dev;
|
||||
int i;
|
||||
|
||||
if (len == 0)
|
||||
return 1.0;
|
||||
|
@ -44,7 +45,7 @@ static float AmpStat(float *data, int len)
|
|||
sum = 0.0;
|
||||
sumofsquares = 0.0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
float x = fabs(data[i]);
|
||||
sum += x;
|
||||
sumofsquares += x * x;
|
||||
|
@ -58,31 +59,29 @@ static float AmpStat(float *data, int len)
|
|||
return dev;
|
||||
}
|
||||
|
||||
static float JumpStat(float *data, int len)
|
||||
static float JumpStat(float *data, size_t len)
|
||||
{
|
||||
float avg;
|
||||
int i;
|
||||
|
||||
/* Calculate 1.0 - avg jump
|
||||
* A score near 1.0 means avg jump is pretty small
|
||||
*/
|
||||
|
||||
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 = 1.0 - (avg / (len - 1) / 2.0);
|
||||
|
||||
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 a1=0, a2=0;
|
||||
float sum=0;
|
||||
|
||||
for (i = 1; i < len; i++) {
|
||||
for (size_t i = 1; i < len; i++) {
|
||||
a2 = a1;
|
||||
v2 = v1;
|
||||
v1 = data[i]-data[i-1];
|
||||
|
@ -93,12 +92,11 @@ static float SecondDStat(float *data, int len)
|
|||
return sum/len;
|
||||
}
|
||||
|
||||
static float RedundantStereo(float *data, int len)
|
||||
static float RedundantStereo(float *data, size_t len)
|
||||
{
|
||||
int i;
|
||||
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]) ||
|
||||
2*fabs(data[i + 1] - data[i]) < fabs(data[i] - data[i - 1]))
|
||||
c++;
|
||||
|
@ -109,14 +107,13 @@ static float RedundantStereo(float *data, int len)
|
|||
static void ExtractFloats(bool doublePrec,
|
||||
bool bigendian,
|
||||
bool stereo,
|
||||
int offset,
|
||||
char *rawData, int dataSize,
|
||||
float *data1, float *data2, int *len1, int *len2)
|
||||
size_t offset,
|
||||
char *rawData, size_t dataSize,
|
||||
float *data1, float *data2, size_t *len1, size_t *len2)
|
||||
{
|
||||
int rawCount = 0;
|
||||
int dataCount1 = 0;
|
||||
int dataCount2 = 0;
|
||||
int i;
|
||||
size_t rawCount = 0;
|
||||
size_t dataCount1 = 0;
|
||||
size_t dataCount2 = 0;
|
||||
bool swap;
|
||||
|
||||
*len1 = 0;
|
||||
|
@ -124,7 +121,7 @@ static void ExtractFloats(bool doublePrec,
|
|||
|
||||
if (offset) {
|
||||
rawData += offset;
|
||||
dataSize -= offset;
|
||||
dataSize -= std::min(dataSize, offset);
|
||||
}
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
|
@ -142,10 +139,10 @@ static void ExtractFloats(bool doublePrec,
|
|||
u.d = 0.0f;
|
||||
while (rawCount + 7 < dataSize) {
|
||||
if (swap)
|
||||
for(i=0; i<8; i++)
|
||||
for(size_t i = 0; i < 8; i++)
|
||||
u.c[7-i] = rawData[rawCount+i];
|
||||
else
|
||||
for(i=0; i<8; i++)
|
||||
for(size_t i = 0; i < 8; i++)
|
||||
u.c[i] = rawData[rawCount+i];
|
||||
data1[dataCount1] = (float)u.d;
|
||||
dataCount1++;
|
||||
|
@ -161,10 +158,10 @@ static void ExtractFloats(bool doublePrec,
|
|||
u.f = 0.0f;
|
||||
while (rawCount + 3 < dataSize) {
|
||||
if (swap)
|
||||
for(i=0; i<4; i++)
|
||||
for(size_t i = 0; i < 4; i++)
|
||||
u.c[3-i] = rawData[rawCount+i];
|
||||
else
|
||||
for(i=0; i<4; i++)
|
||||
for(size_t i = 0; i < 4; i++)
|
||||
u.c[i] = rawData[rawCount+i];
|
||||
data1[dataCount1] = u.f;
|
||||
dataCount1++;
|
||||
|
@ -174,7 +171,7 @@ static void ExtractFloats(bool doublePrec,
|
|||
|
||||
if (stereo) {
|
||||
dataCount1 /= 2;
|
||||
for(i=0; i<dataCount1; i++) {
|
||||
for(size_t i = 0; i < dataCount1; i++) {
|
||||
data2[i] = data1[2*i+1];
|
||||
data1[i] = data1[2*i];
|
||||
}
|
||||
|
@ -191,12 +188,11 @@ static void Extract(bool bits16,
|
|||
bool bigendian,
|
||||
bool offset,
|
||||
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;
|
||||
int dataCount1 = 0;
|
||||
int dataCount2 = 0;
|
||||
int i;
|
||||
size_t rawCount = 0;
|
||||
size_t dataCount1 = 0;
|
||||
size_t dataCount2 = 0;
|
||||
|
||||
*len1 = 0;
|
||||
*len2 = 0;
|
||||
|
@ -275,7 +271,7 @@ static void Extract(bool bits16,
|
|||
|
||||
if (stereo) {
|
||||
dataCount1 /= 2;
|
||||
for(i=0; i<dataCount1; i++) {
|
||||
for(size_t i = 0; i < dataCount1; i++) {
|
||||
data2[i] = data1[2*i+1];
|
||||
data1[i] = data1[2*i];
|
||||
}
|
||||
|
@ -286,33 +282,27 @@ static void Extract(bool bits16,
|
|||
*len2 = dataCount2;
|
||||
}
|
||||
|
||||
static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
|
||||
int *out_offset, unsigned *out_channels)
|
||||
static int GuessFloatFormats(unsigned numTests, const ArrayOf<char> rawData[], size_t dataSize,
|
||||
size_t *out_offset, unsigned *out_channels)
|
||||
{
|
||||
int format;
|
||||
int bestOffset = 0;
|
||||
size_t bestOffset = 0;
|
||||
int bestEndian = 0;
|
||||
int bestPrec = 0;
|
||||
float bestSmoothAvg = 1000.0;
|
||||
int offset;
|
||||
int endian;
|
||||
int prec;
|
||||
float *data1, *data2;
|
||||
int len1;
|
||||
int len2;
|
||||
int test;
|
||||
int i;
|
||||
size_t len1;
|
||||
size_t len2;
|
||||
bool guessStereo = false;
|
||||
int stereoVotes = 0;
|
||||
int monoVotes = 0;
|
||||
unsigned stereoVotes = 0;
|
||||
unsigned monoVotes = 0;
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
FILE *af = g_raw_debug_file;
|
||||
fprintf(af, "Testing float\n");
|
||||
#endif
|
||||
|
||||
data1 = (float *)malloc((dataSize + 4) * sizeof(float));
|
||||
data2 = (float *)malloc((dataSize + 4) * sizeof(float));
|
||||
ArrayOf<float> data1{ dataSize + 4 };
|
||||
ArrayOf<float> data2{ dataSize + 4 };
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
for(prec=0; prec<2; prec++) {
|
||||
for(endian=0; endian<2; endian++) {
|
||||
for(offset=0; offset<(4*prec+4); offset++) {
|
||||
int finiteVotes = 0;
|
||||
int maxminVotes = 0;
|
||||
for(int prec = 0; prec < 2; prec++) {
|
||||
for(int endian = 0; endian < 2; endian++) {
|
||||
for(size_t offset = 0; offset < (4 * prec + 4); offset++) {
|
||||
unsigned finiteVotes = 0;
|
||||
unsigned maxminVotes = 0;
|
||||
float smoothAvg = 0;
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "prec=%d endian=%d offset=%d\n",
|
||||
prec, endian, offset);
|
||||
prec, endian, (int)offset);
|
||||
#endif
|
||||
|
||||
for(test=0; test<numTests; test++) {
|
||||
for(unsigned test = 0; test < numTests; test++) {
|
||||
float min, max;
|
||||
|
||||
ExtractFloats(prec?true:false, endian?true:false,
|
||||
ExtractFloats(prec == 1, endian == 1,
|
||||
true, /* stereo */
|
||||
offset,
|
||||
rawData[test], dataSize,
|
||||
data1, data2, &len1, &len2);
|
||||
rawData[test].get(), dataSize,
|
||||
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) ||
|
||||
!(data2[i]>=0 || data2[i]<=0))
|
||||
break;
|
||||
|
@ -362,13 +353,13 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
|
|||
|
||||
min = data1[0];
|
||||
max = data1[0];
|
||||
for(i=1; i<len1; i++) {
|
||||
for(i = 1; i < len1; i++) {
|
||||
if (data1[i]<min)
|
||||
min = data1[i];
|
||||
if (data1[i]>max)
|
||||
max = data1[i];
|
||||
}
|
||||
for(i=1; i<len2; i++) {
|
||||
for(i = 1; i < len2; i++) {
|
||||
if (data2[i]<min)
|
||||
min = data2[i];
|
||||
if (data2[i]>max)
|
||||
|
@ -379,13 +370,13 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
|
|||
max > 0.01 && max <= 100000)
|
||||
maxminVotes++;
|
||||
|
||||
smoothAvg += SecondDStat(data1, len1) / max;
|
||||
smoothAvg += SecondDStat(data1.get(), len1) / max;
|
||||
}
|
||||
|
||||
smoothAvg /= numTests;
|
||||
|
||||
#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,
|
||||
smoothAvg);
|
||||
#endif
|
||||
|
@ -410,11 +401,8 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
|
|||
* main function will try guessing an integer format.
|
||||
*/
|
||||
|
||||
if (bestSmoothAvg >= 1000.0) {
|
||||
free(data1);
|
||||
free(data2);
|
||||
if (bestSmoothAvg >= 1000.0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
float leftChannel, rightChannel, combinedChannel;
|
||||
|
||||
ExtractFloats(bestPrec?true:false, bestEndian?true:false,
|
||||
ExtractFloats(bestPrec == 1, bestEndian == 1,
|
||||
true, /* stereo */
|
||||
bestOffset,
|
||||
rawData[test], dataSize,
|
||||
data1, data2, &len1, &len2);
|
||||
leftChannel = JumpStat(data1, len1);
|
||||
rightChannel = JumpStat(data2, len2);
|
||||
ExtractFloats(bestPrec?true:false, bestEndian?true:false,
|
||||
rawData[test].get(), dataSize,
|
||||
data1.get(), data2.get(), &len1, &len2);
|
||||
leftChannel = JumpStat(data1.get(), len1);
|
||||
rightChannel = JumpStat(data2.get(), len2);
|
||||
ExtractFloats(bestPrec == 1, bestEndian == 1,
|
||||
false, /* stereo */
|
||||
bestOffset,
|
||||
rawData[test], dataSize,
|
||||
data1, data2, &len1, &len2);
|
||||
combinedChannel = JumpStat(data1, len1);
|
||||
rawData[test].get(), dataSize,
|
||||
data1.get(), data2.get(), &len1, &len2);
|
||||
combinedChannel = JumpStat(data1.get(), len1);
|
||||
|
||||
if (leftChannel > combinedChannel
|
||||
&& rightChannel > combinedChannel)
|
||||
|
@ -447,30 +435,27 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
|
|||
}
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "stereo: %d mono: %d\n", stereoVotes, monoVotes);
|
||||
fprintf(af, "stereo: %ud mono: %ud\n", stereoVotes, monoVotes);
|
||||
#endif
|
||||
|
||||
if (stereoVotes > monoVotes)
|
||||
guessStereo = true;
|
||||
else
|
||||
guessStereo = false;
|
||||
guessStereo = (stereoVotes > monoVotes);
|
||||
|
||||
if (guessStereo == false) {
|
||||
if (!guessStereo) {
|
||||
|
||||
/* test for repeated-byte, redundant stereo */
|
||||
|
||||
int rstereoVotes = 0;
|
||||
int rmonoVotes = 0;
|
||||
unsigned rstereoVotes = 0;
|
||||
unsigned rmonoVotes = 0;
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
float redundant;
|
||||
|
||||
ExtractFloats(bestPrec?true:false, bestEndian?true:false,
|
||||
ExtractFloats(bestPrec == 1, bestEndian == 1,
|
||||
false, /* stereo */
|
||||
bestOffset,
|
||||
rawData[test], dataSize,
|
||||
data1, data2, &len1, &len2);
|
||||
redundant = RedundantStereo(data1, len1);
|
||||
rawData[test].get(), dataSize,
|
||||
data1.get(), data2.get(), &len1, &len2);
|
||||
redundant = RedundantStereo(data1.get(), len1);
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "redundant: %f\n", redundant);
|
||||
|
@ -483,11 +468,10 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
|
|||
}
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "rstereo: %d rmono: %d\n", rstereoVotes, rmonoVotes);
|
||||
fprintf(af, "rstereo: %ud rmono: %ud\n", rstereoVotes, rmonoVotes);
|
||||
#endif
|
||||
|
||||
if (rstereoVotes > rmonoVotes)
|
||||
guessStereo = true;
|
||||
guessStereo = (rstereoVotes > rmonoVotes);
|
||||
|
||||
}
|
||||
|
||||
|
@ -515,25 +499,22 @@ static int GuessFloatFormats(int numTests, char **rawData, int dataSize,
|
|||
else
|
||||
format |= SF_ENDIAN_LITTLE;
|
||||
|
||||
free(data1);
|
||||
free(data2);
|
||||
|
||||
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 guessStereo = false;
|
||||
int signvotes = 0;
|
||||
int unsignvotes = 0;
|
||||
int stereoVotes = 0;
|
||||
int monoVotes = 0;
|
||||
float *data1 = (float *)malloc((dataSize + 4) * sizeof(float));
|
||||
float *data2 = (float *)malloc((dataSize + 4) * sizeof(float));
|
||||
int len1;
|
||||
int len2;
|
||||
int test;
|
||||
unsigned signvotes = 0;
|
||||
unsigned unsignvotes = 0;
|
||||
unsigned stereoVotes = 0;
|
||||
unsigned monoVotes = 0;
|
||||
|
||||
ArrayOf<float> data1 { dataSize + 4 };
|
||||
ArrayOf<float> data2 { dataSize + 4 };
|
||||
size_t len1;
|
||||
size_t len2;
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
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.
|
||||
*/
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
float signL, signR, unsignL, unsignR;
|
||||
|
||||
Extract(0, 1, 1, 0, /* 8-bit signed stereo */
|
||||
false, rawData[test], dataSize,
|
||||
data1, data2, &len1, &len2);
|
||||
signL = JumpStat(data1, len1);
|
||||
signR = JumpStat(data2, len2);
|
||||
false, rawData[test].get(), dataSize,
|
||||
data1.get(), data2.get(), &len1, &len2);
|
||||
signL = JumpStat(data1.get(), len1);
|
||||
signR = JumpStat(data2.get(), len2);
|
||||
Extract(0, 0, 1, 0, /* 8-bit unsigned stereo */
|
||||
false, rawData[test], dataSize,
|
||||
data1, data2, &len1, &len2);
|
||||
unsignL = JumpStat(data1, len1);
|
||||
unsignR = JumpStat(data2, len2);
|
||||
false, rawData[test].get(), dataSize,
|
||||
data1.get(), data2.get(), &len1, &len2);
|
||||
unsignL = JumpStat(data1.get(), len1);
|
||||
unsignR = JumpStat(data2.get(), len2);
|
||||
|
||||
if (signL > unsignL)
|
||||
signvotes++;
|
||||
|
@ -577,13 +558,10 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
|
|||
}
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "sign: %d unsign: %d\n", signvotes, unsignvotes);
|
||||
fprintf(af, "sign: %ud unsign: %ud\n", signvotes, unsignvotes);
|
||||
#endif
|
||||
|
||||
if (signvotes > unsignvotes)
|
||||
guessSigned = true;
|
||||
else
|
||||
guessSigned = false;
|
||||
guessSigned = (signvotes > unsignvotes);
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
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.
|
||||
*/
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
float leftChannel, rightChannel, combinedChannel;
|
||||
|
||||
Extract(0, guessSigned, 1, 0, 0, rawData[test], dataSize, data1,
|
||||
data2, &len1, &len2);
|
||||
leftChannel = JumpStat(data1, len1);
|
||||
rightChannel = JumpStat(data2, len2);
|
||||
Extract(0, guessSigned, 0, 0, 0, rawData[test], dataSize, data1,
|
||||
data2, &len1, &len2);
|
||||
combinedChannel = JumpStat(data1, len1);
|
||||
Extract(0, guessSigned, 1, 0, 0, rawData[test].get(), dataSize, data1.get(),
|
||||
data2.get(), &len1, &len2);
|
||||
leftChannel = JumpStat(data1.get(), len1);
|
||||
rightChannel = JumpStat(data2.get(), len2);
|
||||
Extract(0, guessSigned, 0, 0, 0, rawData[test].get(), dataSize, data1.get(),
|
||||
data2.get(), &len1, &len2);
|
||||
combinedChannel = JumpStat(data1.get(), len1);
|
||||
|
||||
if (leftChannel > combinedChannel
|
||||
&& rightChannel > combinedChannel)
|
||||
|
@ -617,27 +595,24 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
|
|||
}
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "stereo: %d mono: %d\n", stereoVotes, monoVotes);
|
||||
fprintf(af, "stereo: %ud mono: %ud\n", stereoVotes, monoVotes);
|
||||
#endif
|
||||
|
||||
if (stereoVotes > monoVotes)
|
||||
guessStereo = true;
|
||||
else
|
||||
guessStereo = false;
|
||||
guessStereo = (stereoVotes > monoVotes);
|
||||
|
||||
if (guessStereo == false) {
|
||||
if (!guessStereo) {
|
||||
|
||||
/* test for repeated-byte, redundant stereo */
|
||||
|
||||
int rstereoVotes = 0;
|
||||
int rmonoVotes = 0;
|
||||
unsigned rstereoVotes = 0;
|
||||
unsigned rmonoVotes = 0;
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
float redundant;
|
||||
|
||||
Extract(0, guessSigned, 0, 0, 0, rawData[test], dataSize,
|
||||
data1, data2, &len1, &len2);
|
||||
redundant = RedundantStereo(data1, len1);
|
||||
Extract(0, guessSigned, 0, 0, 0, rawData[test].get(), dataSize,
|
||||
data1.get(), data2.get(), &len1, &len2);
|
||||
redundant = RedundantStereo(data1.get(), len1);
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
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
|
||||
fprintf(af, "rstereo: %d rmono: %d\n", rstereoVotes, rmonoVotes);
|
||||
fprintf(af, "rstereo: %ud rmono: %ud\n", rstereoVotes, rmonoVotes);
|
||||
#endif
|
||||
|
||||
if (rstereoVotes > rmonoVotes)
|
||||
guessStereo = true;
|
||||
guessStereo = (rstereoVotes > rmonoVotes);
|
||||
|
||||
}
|
||||
|
||||
|
@ -665,9 +639,6 @@ static int Guess8Bit(int numTests, char **rawData, int dataSize, unsigned *out_c
|
|||
fprintf(af, "mono\n");
|
||||
#endif
|
||||
|
||||
free(data1);
|
||||
free(data2);
|
||||
|
||||
if (guessStereo)
|
||||
*out_channels = 2;
|
||||
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;
|
||||
}
|
||||
|
||||
static int Guess16Bit(int numTests, char **rawData,
|
||||
int dataSize, bool evenMSB,
|
||||
int *out_offset, unsigned *out_channels)
|
||||
static int Guess16Bit(unsigned numTests, const ArrayOf<char> rawData[],
|
||||
size_t dataSize, bool evenMSB,
|
||||
size_t *out_offset, unsigned *out_channels)
|
||||
{
|
||||
int format;
|
||||
bool guessSigned = false;
|
||||
bool guessStereo = false;
|
||||
bool guessBigEndian = false;
|
||||
bool guessOffset = false;
|
||||
int signvotes = 0;
|
||||
int unsignvotes = 0;
|
||||
int stereoVotes = 0;
|
||||
int monoVotes = 0;
|
||||
int formerVotes = 0;
|
||||
int latterVotes = 0;
|
||||
char *rawData2 = (char *)malloc(dataSize + 4);
|
||||
float *data1 = (float *)malloc((dataSize + 4) * sizeof(float));
|
||||
float *data2 = (float *)malloc((dataSize + 4) * sizeof(float));
|
||||
int len1;
|
||||
int len2;
|
||||
int test;
|
||||
unsigned signvotes = 0;
|
||||
unsigned unsignvotes = 0;
|
||||
unsigned stereoVotes = 0;
|
||||
unsigned monoVotes = 0;
|
||||
unsigned formerVotes = 0;
|
||||
unsigned latterVotes = 0;
|
||||
ArrayOf<char> rawData2{ dataSize + 4 };
|
||||
ArrayOf<float> data1{ dataSize + 4 };
|
||||
ArrayOf<float> data2{ dataSize + 4 };
|
||||
size_t len1;
|
||||
size_t len2;
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
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.
|
||||
*/
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
|
||||
float signL, signR, unsignL, unsignR;
|
||||
int i;
|
||||
|
||||
/* 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)];
|
||||
|
||||
/* Test signed/unsigned of the MSB */
|
||||
|
||||
Extract(0, 1, 1, 0, /* 8-bit signed stereo */
|
||||
0, rawData2, dataSize / 2, data1, data2, &len1, &len2);
|
||||
signL = JumpStat(data1, len1);
|
||||
signR = JumpStat(data2, len2);
|
||||
0, rawData2.get(), dataSize / 2, data1.get(), data2.get(), &len1, &len2);
|
||||
signL = JumpStat(data1.get(), len1);
|
||||
signR = JumpStat(data2.get(), len2);
|
||||
Extract(0, 0, 1, 0, /* 8-bit unsigned stereo */
|
||||
0, rawData2, dataSize / 2, data1, data2, &len1, &len2);
|
||||
unsignL = JumpStat(data1, len1);
|
||||
unsignR = JumpStat(data2, len2);
|
||||
0, rawData2.get(), dataSize / 2, data1.get(), data2.get(), &len1, &len2);
|
||||
unsignL = JumpStat(data1.get(), len1);
|
||||
unsignR = JumpStat(data2.get(), len2);
|
||||
|
||||
if (signL > unsignL)
|
||||
signvotes++;
|
||||
|
@ -743,13 +712,10 @@ static int Guess16Bit(int numTests, char **rawData,
|
|||
}
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "sign: %d unsign: %d\n", signvotes, unsignvotes);
|
||||
fprintf(af, "sign: %ud unsign: %ud\n", signvotes, unsignvotes);
|
||||
#endif
|
||||
|
||||
if (signvotes > unsignvotes)
|
||||
guessSigned = true;
|
||||
else
|
||||
guessSigned = false;
|
||||
guessSigned = (signvotes > unsignvotes);
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
if (guessSigned)
|
||||
|
@ -762,22 +728,21 @@ static int Guess16Bit(int numTests, char **rawData,
|
|||
* Test mono/stereo using only the MSB
|
||||
*/
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
float leftChannel, rightChannel, combinedChannel;
|
||||
int i;
|
||||
|
||||
/* 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)];
|
||||
|
||||
Extract(0, guessSigned, 1, 0, 0,
|
||||
rawData2, dataSize / 2, data1, data2, &len1, &len2);
|
||||
leftChannel = JumpStat(data1, len1);
|
||||
rightChannel = JumpStat(data2, len2);
|
||||
rawData2.get(), dataSize / 2, data1.get(), data2.get(), &len1, &len2);
|
||||
leftChannel = JumpStat(data1.get(), len1);
|
||||
rightChannel = JumpStat(data2.get(), len2);
|
||||
Extract(0, guessSigned, 0, 0, 0,
|
||||
rawData2, dataSize / 2, data1, data2, &len1, &len2);
|
||||
combinedChannel = JumpStat(data1, len1);
|
||||
rawData2.get(), dataSize / 2, data1.get(), data2.get(), &len1, &len2);
|
||||
combinedChannel = JumpStat(data1.get(), len1);
|
||||
|
||||
if (leftChannel > combinedChannel
|
||||
&& rightChannel > combinedChannel)
|
||||
|
@ -787,35 +752,31 @@ static int Guess16Bit(int numTests, char **rawData,
|
|||
}
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "stereoVotes: %d monoVotes: %d\n", stereoVotes, monoVotes);
|
||||
fprintf(af, "stereoVotes: %ud monoVotes: %ud\n", stereoVotes, monoVotes);
|
||||
#endif
|
||||
|
||||
if (stereoVotes > monoVotes)
|
||||
guessStereo = true;
|
||||
else
|
||||
guessStereo = false;
|
||||
guessStereo = (stereoVotes > monoVotes);
|
||||
|
||||
if (guessStereo == false) {
|
||||
if (!guessStereo) {
|
||||
|
||||
/* Test for repeated-byte, redundant stereo */
|
||||
|
||||
int rstereoVotes = 0;
|
||||
int rmonoVotes = 0;
|
||||
unsigned rstereoVotes = 0;
|
||||
unsigned rmonoVotes = 0;
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
|
||||
float redundant;
|
||||
int i;
|
||||
|
||||
/* 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)];
|
||||
|
||||
Extract(0, guessSigned, 0, 0, 0, rawData2, dataSize / 2,
|
||||
data1, data2, &len1, &len2);
|
||||
Extract(0, guessSigned, 0, 0, 0, rawData2.get(), dataSize / 2,
|
||||
data1.get(), data2.get(), &len1, &len2);
|
||||
|
||||
redundant = RedundantStereo(data1, len1);
|
||||
redundant = RedundantStereo(data1.get(), len1);
|
||||
|
||||
if (redundant > 0.8)
|
||||
rstereoVotes++;
|
||||
|
@ -824,12 +785,11 @@ static int Guess16Bit(int numTests, char **rawData,
|
|||
}
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "rstereoVotes: %d rmonoVotes: %d\n",
|
||||
fprintf(af, "rstereoVotes: %ud rmonoVotes: %ud\n",
|
||||
rstereoVotes, rmonoVotes);
|
||||
#endif
|
||||
|
||||
if (rstereoVotes > rmonoVotes)
|
||||
guessStereo = true;
|
||||
guessStereo = (rstereoVotes > rmonoVotes);
|
||||
|
||||
}
|
||||
|
||||
|
@ -854,29 +814,29 @@ static int Guess16Bit(int numTests, char **rawData,
|
|||
fprintf(af, "evenMSB: %d BE: %d\n", evenMSB, guessBigEndian);
|
||||
#endif
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
|
||||
float former, latter;
|
||||
int i, offs;
|
||||
int offs;
|
||||
|
||||
/* Extract a NEW array of the MSBs only: */
|
||||
|
||||
if (guessStereo)
|
||||
for (i = 0; i < (dataSize/4)-1; i++)
|
||||
for (size_t i = 0; i + 1 < (dataSize / 4); i++)
|
||||
rawData2[i] =
|
||||
rawData[test][4 * i + (evenMSB ? 0 : 1)];
|
||||
else
|
||||
for (i = 0; i < (dataSize/2)-1; i++)
|
||||
for (size_t i = 0; i + 1 < (dataSize / 2); i++)
|
||||
rawData2[i] =
|
||||
rawData[test][2 * i + (evenMSB ? 0 : 1)];
|
||||
|
||||
former = 0.0;
|
||||
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);
|
||||
|
||||
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] &&
|
||||
rawData2[offs+i]==rawData2[offs+i-1]+1 &&
|
||||
rawData2[offs+i]==rawData2[offs+i+1]) {
|
||||
|
@ -886,12 +846,12 @@ static int Guess16Bit(int numTests, char **rawData,
|
|||
|
||||
latter = 0.0;
|
||||
Extract(1, guessSigned, guessStereo, !guessBigEndian,
|
||||
!guessOffset, rawData[test], dataSize, data1, data2,
|
||||
!guessOffset, rawData[test].get(), dataSize, data1.get(), data2.get(),
|
||||
&len1, &len2);
|
||||
|
||||
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] &&
|
||||
rawData2[offs+i]==rawData2[offs+i-1]+1 &&
|
||||
rawData2[offs+i]==rawData2[offs+i+1]) {
|
||||
|
@ -911,7 +871,7 @@ static int Guess16Bit(int numTests, char **rawData,
|
|||
}
|
||||
|
||||
#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);
|
||||
#endif
|
||||
|
||||
|
@ -950,29 +910,23 @@ static int Guess16Bit(int numTests, char **rawData,
|
|||
else
|
||||
*out_channels = 1;
|
||||
|
||||
free(rawData2);
|
||||
|
||||
free(data1);
|
||||
free(data2);
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static int GuessIntFormats(int numTests, char **rawData, int dataSize,
|
||||
int *out_offset, unsigned *out_channels)
|
||||
static int GuessIntFormats(unsigned numTests, const ArrayOf<char> rawData[], size_t dataSize,
|
||||
size_t *out_offset, unsigned *out_channels)
|
||||
{
|
||||
int format = SF_FORMAT_RAW;
|
||||
bool guess16bit = false;
|
||||
bool evenMSB;
|
||||
float *data1 = (float *)malloc((dataSize + 4) * sizeof(float));
|
||||
float *data2 = (float *)malloc((dataSize + 4) * sizeof(float));
|
||||
int len1;
|
||||
int len2;
|
||||
int vote8 = 0;
|
||||
int vote16 = 0;
|
||||
int evenMSBVotes = 0;
|
||||
int oddMSBVotes = 0;
|
||||
int test;
|
||||
ArrayOf<float> data1{ dataSize + 4 };
|
||||
ArrayOf<float> data2{ dataSize + 4 };
|
||||
size_t len1;
|
||||
size_t len2;
|
||||
unsigned vote8 = 0;
|
||||
unsigned vote16 = 0;
|
||||
unsigned evenMSBVotes = 0;
|
||||
unsigned oddMSBVotes = 0;
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
FILE *af = g_raw_debug_file;
|
||||
|
@ -993,14 +947,14 @@ static int GuessIntFormats(int numTests, char **rawData, int dataSize,
|
|||
* with mono or stereo data.
|
||||
*/
|
||||
|
||||
for (test = 0; test < numTests; test++) {
|
||||
for (unsigned test = 0; test < numTests; test++) {
|
||||
float even, odd;
|
||||
|
||||
Extract(0, 1, 1, 0, /* 8-bit signed stereo */
|
||||
false, rawData[test], dataSize,
|
||||
data1, data2, &len1, &len2);
|
||||
even = AmpStat(data1, len1);
|
||||
odd = AmpStat(data2, len2);
|
||||
false, rawData[test].get(), dataSize,
|
||||
data1.get(), data2.get(), &len1, &len2);
|
||||
even = AmpStat(data1.get(), len1);
|
||||
odd = AmpStat(data2.get(), len2);
|
||||
if ((even > 0.15) && (odd > 0.15)) {
|
||||
#if RAW_GUESS_DEBUG
|
||||
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);
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fprintf(af, "evenMSBVote: %d oddMSBVote: %d\n",
|
||||
fprintf(af, "evenMSBVote: %ud oddMSBVote: %ud\n",
|
||||
evenMSBVotes, oddMSBVotes);
|
||||
fprintf(af, "vote8: %d vote16: %d\n", vote8, vote16);
|
||||
fprintf(af, "vote8: %ud vote16: %ud\n", vote8, vote16);
|
||||
#endif
|
||||
|
||||
if (vote8 > vote16)
|
||||
guess16bit = false;
|
||||
else
|
||||
guess16bit = true;
|
||||
guess16bit = (vote8 <= vote16);
|
||||
|
||||
if (!guess16bit)
|
||||
format = Guess8Bit(numTests, rawData, dataSize, out_channels);
|
||||
|
@ -1038,23 +989,18 @@ static int GuessIntFormats(int numTests, char **rawData, int dataSize,
|
|||
dataSize, evenMSB,
|
||||
out_offset, out_channels);
|
||||
|
||||
free(data1);
|
||||
free(data2);
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
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 dataSize = 16384;
|
||||
int format = SF_FORMAT_RAW;
|
||||
FILE *inf;
|
||||
size_t fileLen;
|
||||
char *rawData[numTests];
|
||||
int test;
|
||||
size_t read_data;
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
|
@ -1095,10 +1041,14 @@ int RawAudioGuess(const wxString &in_fname,
|
|||
if (fileLen < dataSize)
|
||||
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;
|
||||
|
||||
rawData[test] = (char *)malloc(dataSize + 4);
|
||||
startPoint = (fileLen - dataSize) * (test + 1) / (numTests + 2);
|
||||
|
||||
/* 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.
|
||||
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)) {
|
||||
perror("fread error in RawAudioGuess");
|
||||
}
|
||||
|
@ -1121,17 +1071,18 @@ int RawAudioGuess(const wxString &in_fname,
|
|||
* almost anything looks like it could be integer data...
|
||||
*/
|
||||
|
||||
format = GuessFloatFormats(numTests, rawData, dataSize,
|
||||
format = GuessFloatFormats(numTests,
|
||||
rawData.get(),
|
||||
dataSize,
|
||||
out_offset, out_channels);
|
||||
|
||||
if (format == 0) {
|
||||
format = GuessIntFormats(numTests, rawData, dataSize,
|
||||
format = GuessIntFormats(numTests,
|
||||
rawData.get(),
|
||||
dataSize,
|
||||
out_offset, out_channels);
|
||||
}
|
||||
|
||||
for (test = 0; test < numTests; test++)
|
||||
free(rawData[test]);
|
||||
|
||||
#if RAW_GUESS_DEBUG
|
||||
fclose(af);
|
||||
g_raw_debug_file = NULL;
|
||||
|
|
|
@ -25,4 +25,4 @@
|
|||
SF_FORMAT value
|
||||
*/
|
||||
int RawAudioGuess(const wxString &in_fname,
|
||||
int *out_offset, unsigned *out_channels);
|
||||
unsigned *out_offset, unsigned *out_channels);
|
||||
|
|
|
@ -43,10 +43,7 @@ extern FFmpegLibs *FFmpegLibsInst();
|
|||
//struct for caching the decoded samples to be used over multiple blockfiles
|
||||
struct FFMpegDecodeCache
|
||||
{
|
||||
FFMpegDecodeCache() {}
|
||||
~FFMpegDecodeCache() { free(samplePtr); }
|
||||
|
||||
uint8_t* samplePtr{};//interleaved samples
|
||||
ArrayOf<uint8_t> samplePtr;//interleaved samples
|
||||
sampleCount start;
|
||||
size_t len;
|
||||
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(actualDecodeStart>start && firstpass) {
|
||||
// find the number of samples for the leading silence
|
||||
|
||||
// UNSAFE_SAMPLE_COUNT_TRUNCATION
|
||||
// -- but used only experimentally as of this writing
|
||||
// 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.
|
||||
// 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->start=start;
|
||||
// 8 bit and 16 bit audio output from ffmpeg means
|
||||
|
@ -413,9 +411,7 @@ int ODFFmpegDecoder::Decode(SampleBuffer & data, sampleFormat & format, sampleCo
|
|||
else
|
||||
cache->samplefmt = AV_SAMPLE_FMT_FLT;
|
||||
|
||||
cache->samplePtr = (uint8_t*) malloc(amt * cache->numChannels * SAMPLE_SIZE(format));
|
||||
|
||||
memset(cache->samplePtr, 0, amt * cache->numChannels * SAMPLE_SIZE(format));
|
||||
cache->samplePtr.reinit(amt * cache->numChannels * SAMPLE_SIZE(format), true);
|
||||
|
||||
InsertCache(std::move(cache));
|
||||
}
|
||||
|
@ -538,27 +534,27 @@ int ODFFmpegDecoder::FillDataFromCache(samplePtr & data, sampleFormat outFormat,
|
|||
{
|
||||
case AV_SAMPLE_FMT_U8:
|
||||
//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;
|
||||
|
||||
case AV_SAMPLE_FMT_S16:
|
||||
//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;
|
||||
|
||||
case AV_SAMPLE_FMT_S32:
|
||||
//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;
|
||||
|
||||
case AV_SAMPLE_FMT_FLT:
|
||||
//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;
|
||||
|
||||
case AV_SAMPLE_FMT_DBL:
|
||||
//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;
|
||||
|
||||
default:
|
||||
|
@ -614,13 +610,13 @@ int ODFFmpegDecoder::DecodeFrame(streamContext *sc, bool flushing)
|
|||
auto cache = make_movable<FFMpegDecodeCache>();
|
||||
//len is number of samples per channel
|
||||
// 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->start = mCurrentPos;
|
||||
cache->samplePtr = (uint8_t*) malloc(sc->m_decodedAudioSamplesValidSiz);
|
||||
cache->samplePtr.reinit(sc->m_decodedAudioSamplesValidSiz);
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ class ODLock {
|
|||
|
||||
private:
|
||||
friend class ODCondition; //needs friendship for wait()
|
||||
pthread_mutex_t mutex ;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
class ODCondition
|
||||
|
|
|
@ -348,10 +348,7 @@ SpectrogramSettings::~SpectrogramSettings()
|
|||
|
||||
void SpectrogramSettings::DestroyWindows()
|
||||
{
|
||||
if (hFFT != NULL) {
|
||||
EndFFT(hFFT);
|
||||
hFFT = NULL;
|
||||
}
|
||||
hFFT.reset();
|
||||
window.reset();
|
||||
dWindow.reset();
|
||||
tWindow.reset();
|
||||
|
@ -420,9 +417,7 @@ void SpectrogramSettings::CacheWindows() const
|
|||
const auto fftLen = WindowSize() * ZeroPaddingFactor();
|
||||
const auto padding = (WindowSize() * (zeroPaddingFactor - 1)) / 2;
|
||||
|
||||
if (hFFT != NULL)
|
||||
EndFFT(hFFT);
|
||||
hFFT = InitializeFFT(fftLen);
|
||||
hFFT = GetFFT(fftLen);
|
||||
RecreateWindow(window, WINDOW, fftLen, padding, windowType, windowSize, scale);
|
||||
if (algorithm == algReassignment) {
|
||||
RecreateWindow(tWindow, TWINDOW, fftLen, padding, windowType, windowSize, scale);
|
||||
|
|
|
@ -13,6 +13,7 @@ Paul Licameli
|
|||
|
||||
#include "../Experimental.h"
|
||||
#include "../SampleFormat.h"
|
||||
#include "../RealFFTf.h"
|
||||
|
||||
#undef SPECTRAL_SELECTION_GLOBAL_SWITCH
|
||||
|
||||
|
@ -153,7 +154,7 @@ public:
|
|||
// Following fields are derived from preferences.
|
||||
|
||||
// Variables used for computing the spectrum
|
||||
mutable FFTParam *hFFT{};
|
||||
mutable HFFT hFFT;
|
||||
mutable Floats window;
|
||||
|
||||
// Two other windows for computing reassigned spectrogram
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
\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.
|
||||
|
||||
\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.
|
||||
|
||||
*//******************************************************************/
|
||||
|
|
Loading…
Reference in New Issue