/*
            __
           / /_______________  ____  ___
          / __/ ___/ ___/ __ \/ __ \/ _ \
         / /_(__  ) /__/ /_/ / /_/ /  __/
         \__/____/\___/\____/ .___/\___/
                           /_/
    
    sound

    By Michael Stevens

    See license.html for copyright information
*/

#include "../include/tscope.h"
#include "../include/tscope/internal.h"

//------------------------------------------------------------------------
// sample routines 

// load a .wav file
SAMPLE *ts_loadsample(char *filename)
{
    if (!_sound_flag)
        _sound_init();

    if (_debug_flag > DEBUG3)
        fprintf(stderr, "loading sample %s\n", filename);

    char filepath[80];
#ifdef ALLEGRO_WINDOWS
    cygwin_conv_to_full_win32_path(filename, filepath);
#else
    strcpy(filepath, filename);
#endif

    SAMPLE *spl;
    spl = load_sample(filepath);
    if (!spl)
        ts_fatal("ts_loadsample: error loading sample");
    return spl;
}

// free memory allocated to .wav file
void ts_killsample(SAMPLE * spl)
{
    if (!spl)
        ts_fatal("ts_killsample: error destroying sample");
    destroy_sample(spl);
}

// play a .wav file
int ts_playsample(SAMPLE * spl)
{
    if (!spl)
        ts_fatal("ts_playsample: error playing sample");
    int ret;
    ret = play_sample(spl, _volume, _pan, 1000, _loop);
    return ret;
}

// change sound parameters while .wav file is played
void ts_adjustsample(SAMPLE * spl)
{
    if (!spl)
        ts_fatal("ts_adjustsample: error adjusting sample");
    adjust_sample(spl, _volume, _pan, 1000, _loop);
}

// stop playing a .wav file
void ts_stopsample(SAMPLE * spl)
{
    if (!spl)
        ts_fatal("ts_stopsample: error stopping sample");
    stop_sample(spl);
}

//------------------------------------------------------------------------
// stream routines 

int _samplesize = 8;
int _stereo = FALSE;

// fill stream buffer with sine wave (1 sample per call)
// default function used by stream buffer functions
unsigned char sine(__int64 sample)
{
    return (sin((sample * 2 * PI) / ((float) _samplerate / _sinefreq)) +
            1) * 128;
}

// pointer to function that fills the stream buffer
unsigned char (*_streamfunc) (__int64) = &sine;


// open the stream buffer
AUDIOSTREAM *ts_makestream()
{
    // prepare audio stream
    if (!_sound_flag)
        _sound_init();

    AUDIOSTREAM *tmp;
    tmp =
        play_audio_stream(_streambufsize, _samplesize, _stereo,
                          _samplerate, _volume, _pan);
    if (!tmp)
        ts_fatal("_openstream: error opening audio stream");
    return tmp;
}

void ts_killstream(AUDIOSTREAM * stream)
{
    if (!stream)
        ts_fatal("ts_killstream: error destroying sound stream");
    stop_audio_stream(stream);
}

// update the stream buffer
void ts_updatestream(AUDIOSTREAM * stream)
{
    unsigned char *p;
    static __int64 j = 0;

    p = get_audio_stream_buffer(stream);
    if (p) {
        int i;
        for (i = 0; i < _streambufsize; i++) {
            j++;
            p[i] = _streamfunc(j);
        }
        free_audio_stream_buffer(stream);
    }
}

// play a stream 
void ts_playstream(__int64 time)
{
    // prepare audio stream
    if (!_sound_flag)
        _sound_init();
    if (!_timer_flag)
        ts_fatal("tt_sound: timer not running yet.");

    AUDIOSTREAM *stream;
    stream = ts_makestream();

    __int64 tm = ts_time();
    do {
        ts_updatestream(stream);
    } while (ts_time() - tm < time);

    ts_killstream(stream);
}

// play a stream until response button is pressed
int ts_rtstream(__int64 * time, __int64 * error, __int64 maxtime)
{

    if (!_sound_flag)
        _sound_init();
    if (!_timer_flag)
        ts_fatal("tt_sound: timer not running yet.");
    if (!_n_active_keys)
        ts_fatal("tt_sound: no response buttons defined yet");

    int usrnput = 0, ddln = 0;
    __int64 prev, start, tm, err;

    AUDIOSTREAM *stream;
    stream = ts_makestream();

    start = prev = ts_time();
    do {
        ts_updatestream(stream);

        // measure the time
        tm = ts_time();
        err = tm - prev;
        prev = tm;
        usrnput = ts_respstatus();

        if (maxtime > 0)
            if (tm - start >= maxtime)
                ddln = 1;
    } while (!usrnput && !ddln);

    // close
    ts_killstream(stream);
    *time = tm;
    *error = err;
    return usrnput;
}

//------------------------------------------------------------------------
// sound parameter functions

// set volume (0-255)
int ts_volume(int volume)
{
    if (volume < 0 || volume > 255)
        ts_fatal("ts_volume: volume must be minimum 0 and maximum 255.");
    int oldval = _volume;
    _volume = volume;
    return oldval;
}

// set pan (0-255)
int ts_pan(int pan)
{
    if (pan < 0 || pan > 255)
        ts_fatal("ts_pan: pan must be minimum 0 and maximum 255.");
    int oldval = _pan;
    _pan = pan;
    return oldval;
}

// play sample once or looped
int ts_loop(int loop)
{
    int oldval = _loop;
    if (loop)
        _loop = ON;
    else
        _loop = OFF;
    return oldval;
}

// set freq of sine function
int ts_sinefreq(int freq)
{
    if (freq < 0 || freq > _samplerate / 2)
        ts_fatal
            ("ts_sinefreq: frequency must be minimum 0 and maximum half the samplerate.");
    int oldfreq = _sinefreq;
    _sinefreq = freq;
    return oldfreq;
}

// set stream buffer size 
int ts_streambufsize(int size)
{
    int oldsize = _streambufsize;
    _streambufsize = size;
    return oldsize;
}

// set stream sample rate
int ts_samplerate(int rate)
{
    int oldrate = _samplerate;
    _samplerate = rate;
    return oldrate;
}

// change stream function
unsigned char (*ts_streamfunc(unsigned char (*func) (__int64))) (__int64) {
    unsigned char (*oldfunc) (__int64) = _streamfunc;
    _streamfunc = func;
    return oldfunc;
}

// helper function that visualizes a stream function
void ts_drawsound()
{
    // prepare the screen
    int oldfg = ts_fgcolor(WHITE);
    int oldbg = ts_bgcolor(BLACK);
    int oldcoords = ts_coordinates(STANDARD);
    int oldfill = ts_fill(OFF);
    int oldfont = ts_setfont(0);

    // compute button coordinates
    int i;
    struct {
        int x1, x2, y1, y2;
    } button[5];
    for (i = 0; i < 5; i++) {
        button[i].x1 = (SXMAX / 2) - 40 + 20 * i;
        button[i].x2 = button[i].x1 + 20;
        button[i].y1 = 7 * SYMAX / 8 - 10;
        button[i].y2 = 7 * SYMAX / 8 + 10;
    }

    int ok;
    float ratio = 1;
    do {
        ts_clrscr();

        // draw waveform
        ts_fgcolor(GREEN);
        int x, y, oldx = 0, oldy = SYMAX / 2;
        for (x = 0; x < SXMAX; x++) {
            y = _streamfunc(x * ratio);
            y = SYMAX / 4 + (y * SYMAX / 2) / 255;
            ts_line(x, y, oldx, oldy);
            oldx = x;
            oldy = y;
        }
        ts_fgcolor(WHITE);

        // draw buttons
        for (i = 0; i < 5; i++)
            ts_rect(button[i].x1, button[i].y1, button[i].x2,
                    button[i].y2);
        ts_printf_centre(button[0].x1 + 10, button[0].y1 + 8, "-");
        ts_printf_centre(button[1].x1 + 10, button[1].y1 + 8, "+");
        ts_printf_centre(button[2].x1 + 10, button[2].y1 + 8, "1");
        ts_printf_centre(button[3].x1 + 10, button[3].y1 + 8, "T");
        ts_printf_centre(button[4].x1 + 10, button[4].y1 + 8, "E");

        // draw some info
        ts_hline(0, SXMAX, SYMAX / 4);
        ts_printf_centre(SXMAX / 2, SYMAX / 4 - 10, "ff");
        ts_hline(0, SXMAX, 3 * SYMAX / 4);
        ts_printf_centre(SXMAX / 2, 3 * SYMAX / 4 + 10, "0");
        ts_printf_centre(SXMAX / 2, SYMAX / 8, "view: %d samples / %f ms",
                         (int) ((float) SXMAX * ratio),
                         ((float) SXMAX * 1000 * ratio) / _samplerate);


        // prepare mouse 
        int resp;
        int xm, ym;
        ok = 0;
        ts_drawmouse();
        do {
            poll_mouse();
            resp = mouse_b & 1;
            if (resp) {
                xm = ts_xmouse();
                ym = ts_ymouse();
                for (i = 0; i < 5; i++)
                    if (ym > button[i].y1 && ym < button[i].y2
                        && xm > button[i].x1 && xm < button[i].x2)
                        ok = i + 1;
            }
        } while (!ok);
        ts_hidemouse();

        if (ok == 1) {
            ratio = ratio / 2;
            ts_wait(mtt(100));
        }
        if (ok == 2) {
            ratio = ratio * 2;
            ts_wait(mtt(100));
        }
        if (ok == 3) {
            ratio = 1;
            ts_wait(mtt(100));
        }
        if (ok == 4)
            ts_playstream(mtt(1000));

    } while (ok != 5);

    // reset parameters to old values
    ts_fgcolor(oldfg);
    ts_bgcolor(oldbg);
    ts_fill(oldfill);
    ts_setfont(oldfont);
    ts_coordinates(oldcoords);
}


top
Persoonlijke pagina Universiteit GentTscope
Allegro | Cygwin | Gcc
© See license.html for copyright information