mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-11 14:41:06 +02:00
... whenever they really describe the size of a buffer that fits in memory, or of a block file (which is never now more than a megabyte and so could be fit in memory all at once), or a part thereof.
294 lines
7.1 KiB
C++
294 lines
7.1 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
CrossFade.cpp
|
|
|
|
*******************************************************************//**
|
|
|
|
\class CrossFader
|
|
\brief Not used by Audacity (yet) apparently work in progress that has
|
|
been abandoned.
|
|
|
|
*//********************************************************************/
|
|
|
|
#include "CrossFade.h"
|
|
|
|
#include "SampleFormat.h"
|
|
#include "WaveClip.h"
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
using std::vector;
|
|
using std::cout;
|
|
using std::endl;
|
|
|
|
CrossFader::CrossFader():
|
|
mType(FT_MIX)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
CrossFader::~CrossFader()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
bool CrossFader::GetSamples(samplePtr buffer, sampleFormat format,
|
|
sampleCount start, size_t len)
|
|
{
|
|
switch (mType)
|
|
{
|
|
case FT_MIX:
|
|
return CrossFadeMix(buffer,format, start,len);
|
|
break;
|
|
case FT_TRIANGULAR:
|
|
return CrossFadeMix(buffer,format, start,len);
|
|
break;
|
|
case FT_EXPONENTIAL:
|
|
default:
|
|
return CrossFadeMix(buffer,format, start,len);
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bool CrossFader::CrossFadeMix(samplePtr buffer, sampleFormat format, sampleCount start, size_t len)
|
|
{
|
|
|
|
std::cout << "Crossfading from " << start.as_long_long()
|
|
<< " to " << ( len + start ).as_long_long()
|
|
<< std::endl;
|
|
|
|
// start refers to the position in the wave.
|
|
|
|
|
|
//just mix the right things together.
|
|
|
|
|
|
//For each relevant clip, we need to construct a buffer.
|
|
//we should use one of the size len, because this has already
|
|
//been determined to be good in Mixer
|
|
|
|
//Go through each clip, adding it to the total in the appropriate way.
|
|
|
|
//this could be 'optimized' by getting all of the sequences and then
|
|
//iterating through each of them.
|
|
|
|
int numclips = mClips.size();
|
|
|
|
//create vectors to store the important info for each clip.
|
|
std::vector<sampleCount> clipStart(numclips);
|
|
std::vector<sampleCount> clipLength(numclips);
|
|
std::vector<Sequence*> tmpSequence(numclips);
|
|
|
|
|
|
unsigned int i = 0;
|
|
//Now, go through the clips and load up the vectors.
|
|
for(const auto &tmpclip: mClips)
|
|
{
|
|
tmpSequence[i] = tmpclip->GetSequence();
|
|
|
|
|
|
//start is the position of the beginning of the buffer
|
|
//relative to the beginning of the clip. It could be negative.
|
|
clipStart[i]= start - tmpclip->GetStartSample();
|
|
|
|
|
|
|
|
//determine the index of the last sample to get, relative to the start of the clip
|
|
|
|
//it will be no longer than the clip itself.
|
|
clipLength[i] = tmpclip->GetNumSamples()-clipStart[i];
|
|
|
|
std::cout << "X:" << " "
|
|
<< clipLength[i].as_long_long()
|
|
<< " "
|
|
<< tmpclip->GetStartSample().as_long_long()
|
|
<< " ";
|
|
//if the buffer ends before the clip does, adjust the length
|
|
if(clipStart[i] + len < clipLength[i])
|
|
{
|
|
clipLength[i] = len + clipStart[i];
|
|
}
|
|
std::cout
|
|
<< clipStart[i].as_long_long()
|
|
<< " "
|
|
<< clipLength[i].as_long_long()
|
|
<< " "
|
|
<< ( clipLength[i] - clipStart[i] ).as_long_long()
|
|
<< std::endl;
|
|
}
|
|
std::cout << "-------------\n";
|
|
|
|
//Now, determine the sample format:
|
|
switch(format) {
|
|
case int16Sample:
|
|
{
|
|
std::cout << "int\n";
|
|
short *dest = (short *)buffer;
|
|
vector<short*> shortSeq;
|
|
|
|
//Copy the sequences over to the NEW vector, casting as you go.
|
|
for(int i = 0; i < numclips; i++)
|
|
// PRL: what the ... ? This cast is just wrong!
|
|
shortSeq.push_back((short*)tmpSequence[i]);
|
|
|
|
|
|
int clips;
|
|
double f;
|
|
//now, shortSeq contains the samples to mix together.
|
|
for (int j = 0; j < len; j++)
|
|
{
|
|
|
|
//Go through each clip
|
|
for(int i = 0; i < numclips; i++)
|
|
{
|
|
clips = 0;
|
|
f = 0;
|
|
if(j + clipStart[i] >= 0 &&
|
|
clipStart[i]+len < clipLength[i])//only copy if we are within the clip
|
|
{
|
|
// UNSAFE_SAMPLE_COUNT_TRUNCATION
|
|
// -- but class CrossFader is not used as of this writing
|
|
f += shortSeq[ i ][ j+ clipStart[i].as_long_long() ];
|
|
clips++;
|
|
}
|
|
|
|
f/= clips;
|
|
|
|
//Do bounds-checking
|
|
if (f > 32767)
|
|
f = 32767;
|
|
if (f < -32768)
|
|
f = -32768;
|
|
|
|
//Set value
|
|
*dest = (short)f;
|
|
}
|
|
dest++;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case int24Sample:
|
|
{
|
|
std::cout << "int24\n";
|
|
int *dest = (int *)buffer;
|
|
vector<int *> intSeq;
|
|
|
|
|
|
//Copy the sequences over to the NEW vector, casting as you go.
|
|
for(int i = 0; i < numclips; i++)
|
|
// Murder most foul! As in the best it is,
|
|
// But this most foul, strange, and unnatural.
|
|
intSeq.push_back((int*)tmpSequence[i]);
|
|
|
|
int clips=0;
|
|
double f;
|
|
//Go through each sample position
|
|
for (int j = 0; j < len; j++) {
|
|
|
|
//go through each clip.
|
|
for(int i= 0; i < numclips; i++)
|
|
{
|
|
clips = 0;
|
|
f = 0;
|
|
|
|
//only copy if we are within the clip
|
|
if(j + clipStart[i] >= 0 && clipStart[i] + len < clipLength[i])
|
|
{
|
|
// UNSAFE_SAMPLE_COUNT_TRUNCATION
|
|
// -- but class CrossFader is not used as of this writing
|
|
f+= intSeq[ i ][ j + clipStart[ i ].as_long_long() ];
|
|
clips++;
|
|
}
|
|
|
|
f /= clips;
|
|
|
|
if (f > 8388607)
|
|
f = 8388607;
|
|
if (f < -8388608)
|
|
f = -8388608;
|
|
*dest = (int)f;
|
|
|
|
}
|
|
dest ++;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case floatSample: {
|
|
std::cout << "float\n";
|
|
float *dest = (float *)buffer;
|
|
vector<float*> floatSeq;
|
|
|
|
int clips = 0;
|
|
float f;
|
|
|
|
//go through each sample position
|
|
for (int j = 0; j < len; j++) {
|
|
|
|
|
|
clips = 0;
|
|
f = 0;
|
|
|
|
for(int i = 0; i < numclips; i++)
|
|
{
|
|
|
|
cout << numclips << " " ;
|
|
|
|
cout <<f << " " ;
|
|
|
|
if(j + clipStart[i] >= 0 &&
|
|
clipStart[i] + j < clipLength[i])//only copy if we are within the clip
|
|
{
|
|
// UNSAFE_SAMPLE_COUNT_TRUNCATION
|
|
// -- but class CrossFader is not used as of this writing
|
|
// -- hey wait, you never even tried to initialize floatSeq,
|
|
// not even with bad casts!!!
|
|
// Subscripts out of bounds, bombs away!!!
|
|
f += floatSeq[ i ][ ( j + clipStart[ i ] ).as_long_long() ];
|
|
clips++;
|
|
}
|
|
cout << f << " "<< i << " "
|
|
<< floatSeq[ i ][ j + clipStart[ i ].as_long_long() ] << "|";
|
|
}
|
|
if(clips == 0)
|
|
*dest = 0.0f;
|
|
else
|
|
{
|
|
|
|
f /= clips;
|
|
cout << f << "--";
|
|
// MM: XXX Should probably go outside the loop
|
|
if (f > 1.0f)
|
|
*dest = 1.0f;
|
|
else if (f < -1.0f)
|
|
*dest = -1.0f;
|
|
else
|
|
*dest = (float)f;
|
|
|
|
}
|
|
cout << *dest << endl;
|
|
dest++;
|
|
}
|
|
} break;
|
|
} // switch
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void CrossFader::ClearClips()
|
|
{
|
|
mClips.clear();
|
|
}
|