audio fade

I was wondering if someone could help me with implementing a logarithmic fade? I’d like to use it to fade up and down sound files…

I’m nearly there but can’t quite get the last bits of the puzzle. I figure I’ll also need an inverse log??

I have:

  
typedef struct {  
    float time;  
    float value;  
} fade;  
  
class Fader : public ofThread {  
  
public:  
  
    Fader(float from, float to, float over, FaderEquation type)  
    :  
    _from(from),  
    _to(to),  
    _logFrom(log(from)),  
    _logTo(log(to)),  
    _over(over),  
    _type(type),  
    _startTime(ofGetElapsedTimeMillis()),  
    _isFading(true) {  
        _fade.time = _startTime;  
        _fade.value = _from;  
        startThread(false, false);  
    };  
  
    ~Fader() {  
        if (isThreadRunning()) stopThread();  
    };  
  
    bool    isFading() {return _isFading;};  
    fade   getFade() {return _fade;};  
  
private:  
  
    float   _from;  
    float   _to;  
    float   _logFrom;  
    float   _logTo;  
    fade    _fade;  
    float   _pct;  
  
    float   _over;  
    float   _startTime;  
    int     _now;  
  
    int     _type;  
    bool    _isFading;  
  
    void threadedFunction() {  
        while(isThreadRunning() != 0) {  
            if(lock()) {  
  
                calculate();  
                // check if is Fader done  
                if (_pct <= 0.0f) {  
                    _fade.value = _to; // conform final value  
                    _fade.time = _over;  
                    _isFading = false;  
                    stopThread();  
                }  
  
            }  
        }  
    }  
  
    inline void calculate() {  
  
        _now = ofGetElapsedTimeMillis() - _startTime;  
  
        switch (_type) {  
            case FADE_LINEAR:  
            {  
                _pct = 1.0 - (_now / _over);  
                break;  
            }  
            case FADE_LOG:  
            {  
                _pct = (log10(_over/_now));  
                break;  
            }  
        }  
  
        _fade.value = (_pct * (_from - _to) + _to);  
        _fade.time  = _now;  
    }  
  
};  

Attached is the source from a testApp I’m using to just visualize what’s happening with the numbers.

src.zip

i think the problem is that log(x) approaches infinity as x approaches 0.

here’s an equation that fixes that:

_pct=ln(_over/(_over + (e-1) * _now)) + 1

ln is natural log and e is the constant.

e.g., http://www.wolframalpha.com/input/?i=plot+y+%3D+ln%284%2F%284+%2B+%28e-1%29*x%29%29%2B1+from+0+to+4

Hey Kyle

Thanks! That totally put me on the right track…and thanks for reminding my about WolframAlpha - I’d totally forgotten about the handy graphing function.

A couple of things I found were:

* ln isn’t defined on my PC…it seems log on Win is log[sub]e[/sub] ?
* I used log10 in the end as this seems closer to what I could find as a ‘natural’ dB damping curve and makes all the maths a little nicer looking…I think the way audio programs work is by changing the log/exp base in order to vary the ‘steepness’ of the attack/dropoff - would be nice to implement this but didn’t have time to figure out how to get the log of any base
* I struggled to figure out how to invert this (ie., do an exponential fade in-out) and ended up having to resort to a magic number:

_pct = -pow(10, ((_now * 1.04 - _over)/_over)) + 1.09;

I have no idea why I have to multiply _now by 1.04…but it was the only way to get the curve to ‘fit’ both time and fade values…

If it’s of any help to someone else I’ve ended up using the following to get ok fades:

  
enum FaderType {  
    FADE_LINEAR,  
    FADE_LOG,  
    FADE_EXP  
};  
  
typedef struct {  
    float time;  
    float value;  
} fade;  
  
class Fader : public ofThread {  
  
public:  
  
    Fader(float from, float to, float over, FaderType type)  
    :  
    _from(from),  
    _to(to),  
    _over(over),  
    _type(type),  
    _startTime(ofGetElapsedTimeMillis()),  
    _isFading(true) {  
        _fade.time = _startTime;  
        _fade.value = _from;  
        startThread(false, false);  
    };  
  
    ~Fader() {  
        if (isThreadRunning()) stopThread();  
    };  
  
    bool    isFading() {return _isFading;};  
    fade   getFade() {return _fade;};  
  
private:  
  
    float   _from;  
    float   _to;  
    fade    _fade;  
    float   _pct;  
  
    float   _over;  
    float   _startTime;  
    int     _now;  
  
    int     _type;  
    bool    _isFading;  
  
    void threadedFunction() {  
        while(isThreadRunning() != 0) {  
            if(lock()) {  
  
                calculate();  
                // check if is Fader done  
                if (_fade.time >= _over) {  
                    _fade.value = _to; // conform final value  
                    _fade.time = _over;  
                    _isFading = false;  
                    stopThread();  
                }  
  
            }  
        }  
    }  
  
    inline void calculate() {  
  
        _now = ofGetElapsedTimeMillis() - _startTime;  
  
        switch (_type) {  
            case FADE_LINEAR:  
            {  
                _pct = 1.0 - (_now / _over);  
                break;  
            }  
            case FADE_LOG:  
            {  
                float base = 10; //2.71828182845904523536028747135266249775724709369995;  
                _pct = log10(_over/(_over + (base-1) * _now)) + 1;  
                break;  
            }  
            case FADE_EXP:  
            {  
                float base = 10.0f;  
                _pct = -pow((double)base, (double)((_now * 1.04 - _over)/_over)) + 1.09;  
                break;  
            }  
        }  
  
        _fade.value = (_pct * (_from - _to) + _to);  
        _fade.time  = _now;  
    }  
  
};  
  

Hello Matt,

this is exactly what I was looking for. However, I have just started with oF. Could you give an example of how you use it to fade out a sound file?

I am re-programming an app I once built for school children in Max/MSP. It is basically a very simple sampler. The kids see a computer keyboard on the screen, can drag and drop samples onto the keys and then, when pressing those keys on the real computer keyboard, can play back the according samples. The samples play as long, as the keys are pressed down. When the key is released the according sample stops.Now, I want to call your fader when a key is released and only afterwards stop the sample. I am not sure how to call the Fader and also am not sure how to stop the playback only after the time of the fading has passed…

I would appreciate a simple example of how you used it…

Thanks a lot!
Best,
IOhanna

Hi Hanna

Sorry for the delay in getting back to you.

I’ve cleaned up the Fader.h class a little bit and made two examples.

The first draws the fades and shows a simple sound fade; the second pretty much does what you want (I think) - I tried to come up with something that demonstrated the idea without actually doing the key/play sound idea, but in the end it was easiest to just try it out…

Because of the nature of threads and copy constructors I’ve had to make the Fader class work only as a pointer. I’m not sure how far down the c++ track you’ve come with pointers and references, but it does make using this class a little unwieldy…I’m sure there’s a nicer/simpler way, particularly if all you need is fade up and down of a sound file (ie., you could modify the guts of the Fader.h class so that everything that gets called in the threadedFunction() actually happens in an update method)…but I wanted to use it for several things (fades to black, etc) so made this class instead.

Anyways, hope it helps!

emptyFader.zip

emptyFaderKeyPress.zip

Thank you so much. I am looking into it right now…I really appreciate it and actually I am glad you programmed it so flexible and powerful, it already inspired me to use it for visual feedback as well. Perfect. Thanks again!
IOhanna

Hi again,

it is really great and helpful, thanks again!
After playing with it for a while I found out how to crash it by triggering a sample very quickly again and again (pressing the a or b button as fast as I can a few times in a row). I get the same **Mutex_POSIX.h cannot unlock mutex **error message as described on the forum earlier in here (http://forum.openframeworks.cc/t/mutex-posix.h-cannot-unlock-mutex/7073/0)

The output looks like this:

  
Code:  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
OF: OF_VERBOSE: Deleting fade  
OF: OF_VERBOSE: Creating fade  
OF: OF_VERBOSE: Start fade  
terminate called throwing an exception[Switching to process 7871 thread 0x9e0b]  
[Switching to process 7871 thread 0x9e0b]  
sharedlibrary apply-load-rules all  
warning: Could not find object file "/Developer/usr/lib/gcc/i686-apple-darwin10/4.0.1/libgcc.a(_eprintf.o)" - no debug information available for "/var/tmp/gcc_40/gcc_40-5494~211/src/gcc/libgcc2.c".  
  
warning: Could not find object file "/Users/theo/Documents/CODE/__OPENFRAMEWORKS/gitOF/openFrameworks/apps/devApps/macDragDropExample/buildGlutFrameworkHackedWindowLevel10.4/libForeground.a(macx_foreground.o)" - no debug information available for "/Users/mcast/Code/GLUT-ToPost/macx_foreground.m".  
  
(gdb)   
    
Current language:  auto; currently c++    

Do you have any idea what causes it?
In the other post there was some little bug with destroying objects…

I’ll also look into it myself a bit more…

Thanks for you help so far, it has in any way helped me on the right track with fading :slight_smile:
Best wishes!
IOhanna

I’m not super good with mutex and threaded functions :wink:

I think maybe it’s because the way I’ve coded it the mutex’s are actually separate instances, rather than a single static mutex shared between all the threaded instances of the Faders…

I got the idea looking at this contribution to a different problem topic,1335.msg38837.html#msg38837

So basically you have:

  
static ofMutex FadeMutex;  

at the top of Fader.h

and then threadedFunction becomes:

  
    void threadedFunction() {  
        while(isThreadRunning() != 0) {  
            FadeMutex.lock();  
            calculate();  
            // check if the Fader done  
            if (_fade.time >= _over) {  
                _fade.value = _to; // conform final value  
                _fade.time = _over;  
                _isFading = false;  
                stopThread();  
            }  
            FadeMutex.unlock();  
        }  
    }  

Seems to work for me, but perhaps my fingers aren’t fast enough…let me know how you go…

Fader.h

Thanks a lot for this! Just what I was looking for, and it works great.

This is very useful.
I used this code to create a multitrack player with a single ofThread.
Tracks that have to loop start again some time before finishing to create a continuous loop without any interruption. This code has been used to play continuous ambient sounds. The exponential fade is the most natural one for my ears.
It shouldn’t be used with tracks that have a perfect loop and don’t need to crossfade with themselves.
Also the file duration in ms should be greater than the fade duration (now it is 2 seconds).
Supported files: wav, aif, mp3, with sample rate 44100 and bit depth 16bit. Mp3s should be encoded with constant bitrate (this infos are needed to calculate the duration of the audio files since ofSoundPlayer has no method for that).
Works best with wav or aif files, sometimes mp3s don’t start, maybe caused by strange encodings.
It can be improved adding some mutex locking so that tracks can be added on the fly.
For now it is advised to add new tracks before any loading/playing.
Tested with OF 0.9.8 on Ubuntu 16.10 and Mac OS X 10.9.5.
Thank you gameover for your code!
Suggestions or improvements are welcome :wink:
testAudioThread.zip (1.7 MB)