Skip to content

Commit

Permalink
Unit Tests and Sustain Swells for ADSR
Browse files Browse the repository at this point in the history
The ADSR envelope in analog mode didn't allow sustain to
increase. To begin debugging this, add a collection of
unit tests.

Addresses surge-synthesizer#1439
  • Loading branch information
baconpaul committed Jan 6, 2020
1 parent d17183b commit 4cbc074
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/common/dsp/AdsrEnvelope.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ class AdsrEnvelope : public ModulationSource
}
}

int getEnvState() { return envstate; }

private:
ADSRStorage* adsr = nullptr;
SurgeVoiceState* state = nullptr;
Expand Down
86 changes: 86 additions & 0 deletions src/headless/UnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,92 @@ TEST_CASE( "lipol_ps class", "[dsp]" )

}

void copyScenedataSubset(SurgeStorage *storage, int scene, int start, int end) {
int s = storage->getPatch().scene_start[scene];
for(int i=start; i<end; ++i )
{
storage->getPatch().scenedata[scene][i-s].i =
storage->getPatch().param_ptr[i]->val.i;
}
}

void setupStorageRanges(Parameter *start, Parameter *endIncluding,
int &storage_id_start, int &storage_id_end) {
int min_id = 100000, max_id = -1;
Parameter *oap = start;
while( oap <= endIncluding )
{
if( oap->id >= 0 )
{
if( oap->id > max_id ) max_id = oap->id;
if( oap->id < min_id ) min_id = oap->id;
}
oap++;
}

storage_id_start = min_id;
storage_id_end = max_id + 1;
}

TEST_CASE( "ADSR Envelope Behaviour", "[mod]" )
{

std::shared_ptr<SurgeSynthesizer> surge( Surge::Headless::createSurge(44100) );
REQUIRE( surge.get() );

auto* adsrstorage = &(surge->storage.getPatch().scene[0].adsr[0]);
std::shared_ptr<AdsrEnvelope> adsr( new AdsrEnvelope() );
adsr->init( &(surge->storage), adsrstorage, surge->storage.getPatch().scenedata[0], nullptr );
REQUIRE( adsr.get() );

int ids, ide;
setupStorageRanges(&(adsrstorage->a), &(adsrstorage->mode), ids, ide );
REQUIRE( ide > ids );
REQUIRE( ide >= 0 );
REQUIRE( ids >= 0 );

/*
** OK so lets set up a pretty simple setup
*/

auto svn = [](Parameter *p, float vn)
{
p->set_value_f01( p->value_to_normalized( vn ) );
};

auto inverseEnvtime = [](float desiredTime)
{
// 2^x = desired time
auto x = log(desiredTime)/log(2.0);
return x;
};

svn(&(adsrstorage->a), inverseEnvtime(0.2));
svn(&(adsrstorage->d), inverseEnvtime(0.2));
svn(&(adsrstorage->s), 0.0);
svn(&(adsrstorage->r), inverseEnvtime(0.1));

svn(&(adsrstorage->a_s), 0);
svn(&(adsrstorage->d_s), 0);
svn(&(adsrstorage->r_s), 0);

svn(&(adsrstorage->mode),0); // digital

copyScenedataSubset(&(surge->storage), 0, ids, ide);
adsr->attack();
for( int i=0; i<1000; ++i )
{
auto t = 1.0 * (i+1) * BLOCK_SIZE * dsamplerate_inv;
if( i == 600 )
adsr->release();

adsr->process_block();

if( i % 25 == 0 ) std::cout << i << " " << t << " " << adsr->output << " " << adsr->getEnvState()
<< std::endl;
}
}



int runAllTests(int argc, char **argv)
Expand Down

0 comments on commit 4cbc074

Please sign in to comment.