Prepare to support generalized fade-in/outs.

This commit is contained in:
Jonathan Moore Liles 2008-04-14 00:12:05 -05:00
parent ee576b7ff7
commit 91abbf543d
2 changed files with 62 additions and 35 deletions

View File

@ -539,14 +539,11 @@ Region::normalize ( void )
/**********/ /**********/
enum fade_type_e { Linear, Cosine, Logarithmic, Parabolic };
enum fade_dir_e { FADE_IN, FADE_OUT };
/** Return gain for frame /index/ of /nframes/ on a gain curve of type /type/.*/ /** Return gain for frame /index/ of /nframes/ on a gain curve of type /type/.*/
/* FIXME: calling a function per sample is bad, switching on type mid /* FIXME: calling a function per sample is bad, switching on type mid
* fade is bad. */ * fade is bad. */
static inline float static inline float
fade_gain ( fade_type_e type, nframes_t index, nframes_t nframes ) fade_gain ( Region::fade_type_e type, nframes_t index, nframes_t nframes )
{ {
float g = 0; float g = 0;
@ -554,17 +551,17 @@ fade_gain ( fade_type_e type, nframes_t index, nframes_t nframes )
switch ( type ) switch ( type )
{ {
case Linear: case Region::Linear:
g = fi; g = fi;
break; break;
case Cosine: case Region::Cosine:
// g = sin( fi * M_PI / 2 ); // g = sin( fi * M_PI / 2 );
g = (1.0f - cos( fi * M_PI )) / 2.0f; g = (1.0f - cos( fi * M_PI )) / 2.0f;
break; break;
case Logarithmic: case Region::Logarithmic:
g = pow( 0.1f, (1.0f - fi) * 5.0f ); g = pow( 0.1f, (1.0f - fi) * 5.0f );
break; break;
case Parabolic: case Region::Parabolic:
g = 1.0f - (1.0f - fi) * (1.0f - fi); g = 1.0f - (1.0f - fi) * (1.0f - fi);
break; break;
} }
@ -577,25 +574,21 @@ fade_gain ( fade_type_e type, nframes_t index, nframes_t nframes )
* buffer size of /nframes/. /start/ and /end/ are relative to the * buffer size of /nframes/. /start/ and /end/ are relative to the
* given buffer, and /start/ may be negative. */ * given buffer, and /start/ may be negative. */
static void static void
apply_fade ( sample_t *buf, fade_dir_e dir, fade_type_e type, long start, nframes_t end, nframes_t nframes ) apply_fade ( sample_t *buf, Region::fade_dir_e dir, Region::fade_type_e type, long start, nframes_t end, nframes_t nframes )
{ {
float gain = 1.0f; printf( "apply fade %s: start=%ld end=%lu\n", dir == Region::FADE_OUT ? "out" : "in", start, end );
printf( "apply fade %s: start=%ld end=%lu\n", dir == FADE_OUT ? "out" : "in", start, end );
nframes_t i = start > 0 ? start : 0; nframes_t i = start > 0 ? start : 0;
nframes_t e = end > nframes ? nframes : end; nframes_t e = end > nframes ? nframes : end;
float d = dir == FADE_OUT ? 1.0f : -1.0f; if ( dir == Region::FADE_OUT )
if ( dir == FADE_OUT )
for ( ; i < e; ++i ) for ( ; i < e; ++i )
{ {
long n = end - start; long n = end - start;
const float g = fade_gain( type, (n - 1) - (i - start), n); const float g = fade_gain( type, (n - 1) - (i - start), n);
printf( "gain for %lu is %f\n", i, g ); // printf( "gain for %lu is %f\n", i, g );
buf[ i ] *= g; buf[ i ] *= g;
} }
else else
@ -603,7 +596,7 @@ apply_fade ( sample_t *buf, fade_dir_e dir, fade_type_e type, long start, nframe
{ {
const float g = fade_gain( type, i - start, end - start ); const float g = fade_gain( type, i - start, end - start );
printf( "gain for %lu is %f\n", i, g ); // printf( "gain for %lu is %f\n", i, g );
buf[ i ] *= g; buf[ i ] *= g;
} }
} }
@ -756,30 +749,37 @@ Region::read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) co
for ( int i = cnt; i--; ) for ( int i = cnt; i--; )
buf[i] *= _scale; buf[i] *= _scale;
/* TODO: do fade in/out here */
/* perform declicking if necessary */ /* perform declicking if necessary */
/* FIXME: shouldn't this be wallclock time? */ /* FIXME: keep the declick defults someplace else */
const nframes_t declick_frames = 256; Fade declick;
const fade_type_e type = Linear;
declick.length = 256;
declick.type = Linear;
if ( start + cnt + declick_frames > r.end )
{ {
/* declick end */ Fade fade;
const nframes_t d = r.end - start;
apply_fade( buf, FADE_OUT, type , cnt + (long)d - declick_frames, cnt + d, cnt ); fade = declick < _fade_in ? _fade_in : declick;
}
if ( sofs < declick_frames ) /* do fade in if necessary */
if ( sofs < fade.length )
{ {
/* declick start */
const long d = 0 - sofs; const long d = 0 - sofs;
apply_fade( buf + ofs, FADE_IN, type, d, d + declick_frames, cnt - ofs ); apply_fade( buf + ofs, FADE_IN, fade.type, d, d + fade.length, cnt - ofs );
} }
fade = declick < _fade_out ? _fade_out : declick;
/* do fade out if necessary */
if ( start + cnt + fade.length > r.end )
{
const nframes_t d = r.end - start;
apply_fade( buf, FADE_OUT, fade.type, cnt + (long)d - fade.length, cnt + d, cnt );
}
}
// printf( "read %lu frames\n", cnt ); // printf( "read %lu frames\n", cnt );
return cnt; return cnt;

View File

@ -36,12 +36,38 @@ class Region;
class Region_Base : public Track_Widget class Region_Base : public Track_Widget
{ {
public:
enum fade_type_e { Linear, Cosine, Logarithmic, Parabolic };
enum fade_dir_e { FADE_IN, FADE_OUT };
struct Fade
{
fade_type_e type;
nframes_t length;
Fade ( )
{
type = Linear;
length = 0;
}
bool
operator< ( const Fade &rhs )
{
return length < rhs.length;
}
};
private: private:
Audio_File *_clip; /* clip this region represents */ Audio_File *_clip; /* clip this region represents */
float _scale; /* amplitude adjustment */ float _scale; /* amplitude adjustment */
Fade _fade_in;
Fade _fade_out;
protected: protected:
const char *class_name ( void ) { return "Region"; } const char *class_name ( void ) { return "Region"; }
@ -174,6 +200,7 @@ class Region : public Region_Base
public: public:
static Loggable * static Loggable *
create ( char **sa ) create ( char **sa )
{ {