⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 record.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
/* record.c -- keyboard to adagio recorder * Copyright 1989 Carnegie Mellon University * * the interface consists of three routines: *      rec_init()      -- initialization *      rec_event(byte *data)   -- called to insert (record) midi data,  *                              -- returns FALSE if no more space *      rec_final()     -- called to finish up *//******************************************************************************       Change Log*  Date | Change*-----------+-----------------------------------------------------------------* 27-Feb-86 | Created changelog*           | Use pedal information when computing durations (code taken*           |  from transcribe.c)* 23-Mar-86 | Determine size of transcription when rec_init is called.* 21-May-86 | Major rewrite to use continuous controls (code taken *           |  from transcribe.c)*  1-Aug-87 | F.H. Changed rec_init() to new memory handling.* 17-Oct-88 | JCD : portable version.* 31-Jan-90 | GWL : cleaned up for LATTICE* 30-Jun-90 | RBD : further changes*  2-Apr-91 | JDW : further changes* 28-Apr-03 | DM  : changed for portability; true->TRUE, false->FALSE*****************************************************************************/#include "switches.h"#include <stdio.h>#include <stdlib.h>#include "cext.h"#include "midifns.h"#include "userio.h"#include "midicode.h"#include "record.h"#include "cmdline.h"extern long space;    /* how much space is left? */int debug_rec = FALSE;    /* verbose debug flag for this module */long max_notes = -1L;    /* -1 is flag that space must be allocated */time_type previous_time;/***************************************************************** data structure notes: the midi stream is stored as an array * of 4-byte records, each of which is either a time or midi* data.     Midi data always begins with a control byte (high* order bit set), and it is assumed times are positive (high* order bit clear), so the two are easy to distinguish* IF THE COMPILER PUTS THESE BITS IN THE SAME PLACE.  It looks* like the high order byte of the time lines up with the last* byte of a 4 byte array, so we will always set the high order* bit of the last array byte when the first 3 bytes are filled* with MIDI data.  This is refered to as the "tag" bit.* WARNING: Lattice C longs are UNSIGNED, therefore always* positive.  Test the high order bit with a mask.****************************************************************/#define MIDI_CMD_BIT    0x80#define HIGH_BIT        0x80000000#define istime(note) (!(((note)->when) & HIGH_BIT))typedef union note_struct {    byte n[4];    long when;} *note_type, note_node;private note_type event_buff;    /* pointer to allocated buffer */private note_type next;    /* pointer to next entry in buffer */private note_type last;    /* pointer to last entry in buffer */private int pile_ups;    /* inner loop iteration count */private int max_pile_up;    /* maximum of pile_ups */private boolean fixed_octave;	/* used to avoid many error messages *//*****************************************************************************    Routines local to this module****************************************************************************/private void    bend_filter();private void    byteorder();private void    ctrl_filter();private int    event_bend();private void    filter();private long    getdur();private long    getnext();private char    map_ctrl();private void    output();/*****************************************************************************               bend_filter* Inputs:*    note_type note: the current note*    note_type last: the last recorded event*    long now: the current time* Effect:*    remove pitch bend events in same 0.01 sec time slot* Implementation:*    If the current event is a pitch bend that bends again*    in the same time slot, make it a no-op by replacing it with*    the time.****************************************************************************/private void bend_filter(note, last, now)note_type note;    /* current note */note_type last;    /* the last recorded event */long now;       /* the current time */{    /* first see if there is another bend in this time         * slot.         */    note_type note2 = note + 1;    while (note2 < last) {        if (istime(note2) && (note2->when > now)) {            break; /* new time slot */        }         else if (note->n[0] == note2->n[0]) {            note->when = now;            return; /* found another bend */        }        note2++;    }}/*****************************************************************************               byteorder* Effect: *    check out assumptions about byte order and placement****************************************************************************/private void byteorder(){    note_node test_event;    if ((sizeof(test_event) != 4) ||        (sizeof(test_event.when) != 4) ||        (sizeof(test_event.n[0]) != 1)) {        gprintf(ERROR, "implementation error: size problem\n");        EXIT(1);    }    test_event.n[0] = 0x12;    test_event.n[1] = 0x34;    test_event.n[2] = 0x56;    test_event.n[3] = 0x78;    if ((test_event.when != 0x78563412) &&        (test_event.when != 0x12345678)) {        gprintf(ERROR, "implementation error: layout problem\n");        EXIT(1);    }}/*****************************************************************************               ctrl_filter* Inputs:*    note_type note: the current note*    note_type last: the last recorded event*    long now: the current time* Effect:*    remove ctrl change events in same 0.01 sec time slot* Implementation:*    If the current event is a control change that changes again*    in the same time slot, make it a no-op by replacing it with*    the time.****************************************************************************/private void ctrl_filter(note, last, now)note_type note;    /* the current note */note_type last;    /* the last recorded event */long now;       /* the current time */{    /* see if there is another control change in this time         * slot.         */    note_type note2 = note+1;    while (note2 < last) {        if (istime(note2) && (note2->when > now)) {            break;    /* new time slot */        }         else if ((note->n[0] == note2->n[0]) &&            (note->n[1] == note2->n[1])) {            note->when = now;            return; /* found another change */        }        note2++;    }}/*****************************************************************************               event_bend* Inputs:*    note_type note: pointer to a pitch bend event* Outputs:*    returns int: an 8 bit pitch bend number****************************************************************************/private int event_bend(note)note_type note;{    return((int) (((note->n[1]) >> 6) + ((note->n[2]) << 1)));}/*****************************************************************************               filter* Inputs:*    note_type last: the last note recorded* Effect: allow only one control change per time slot (0.01 sec)* Implementation:*    call ctrl_filter and bend_filter to overwrite control changes with*    noop data (the current time is used as a noop)****************************************************************************/private void filter(last)note_type last;{    note_type note;    /* loop control variable */    long now=0;   /* last time seen */    int command;    /* command pointed to by note */    for (note = event_buff; note <= last; note++) {        if (istime(note)) {            now = note->when;        }         else {            command = note->n[0] & MIDI_CODE_MASK;            if (command == MIDI_CTRL &&                note->n[1] == SUSTAIN) {                /* do nothing */;            }             else if (command == MIDI_CTRL) {                ctrl_filter(note, last, now);            }             else if (command == MIDI_TOUCH) {                bend_filter(note, last, now);    /* bend and touch use the */            }             else if (command == MIDI_BEND) {    /*  same filter routines  */                bend_filter(note, last, now);            }        }    }}/*****************************************************************************               getdur* Inputs:*    int i: index of the note*    note_type last: pointer to the last event recorded*    int ped: TRUE if pedal is down at event i*    long now: the time at event i* Outputs:*    returns long: the duration of note i* Assumes:*    assumes i is a note* Implementation:*    This is tricky because of pedal messages.  The note is kept on by*    either the key or the pedal.  Keep 2 flags, key and ped.  Key is*    turned off when a key is released, ped goes off and on with pedal.*    Note ends when (1) both key and ped are FALSE, (2) key is*    pressed (this event will also start another note).****************************************************************************/private long getdur(i, last, ped, now)int i;note_type last;int ped;long now;{    int key = TRUE;    /* flag that says if note is on */    long start = now;    int chan = event_buff[i].n[0] & MIDI_CHN_MASK;    int pitch = event_buff[i].n[1];    note_type note = &(event_buff[i+1]);    int noteon; /* TRUE if a noteon message received on chan */    int keyon;    /* TRUE if noteon message had non-zero velocity */    /* search from the next event (i+1) to the end of the buffer:         */    for (; note < last; note++) {        if (istime(note)) {            now = note->when;        }         else {            noteon = keyon = FALSE;            if ((note->n[0] & MIDI_CHN_MASK) == chan) {                noteon = ((note->n[0] & MIDI_CODE_MASK) == MIDI_ON_NOTE) &&                    (note->n[1] == pitch);                keyon = noteon && (note->n[2] != 0);                if ((noteon && (note->n[2] == 0)) ||                    (((note->n[0] & MIDI_CODE_MASK) == MIDI_OFF_NOTE) &&                    (note->n[1] == pitch))) key = FALSE;                if (((note->n[0] & MIDI_CODE_MASK) == MIDI_CTRL) &&                    note->n[1] == SUSTAIN && note->n[2] == 127) ped = TRUE;                if (((note->n[0] & MIDI_CODE_MASK) == MIDI_CTRL) &&                    note->n[1] == SUSTAIN && note->n[2] == 0) ped = FALSE;                if ((!key && !ped) || keyon)                    return(now - start);            }        }    }    return(last->when - start);}/*****************************************************************************               getnext* Inputs:*    int i: the index of the current note*    note_type last: pointer to last valid data*    long now: the current time* Outputs:*    returns long: the time of the next note, program, or control change*       (returns time of last event if nothing else is found)****************************************************************************/private long getnext(i, last, now)int i;    /* the index of the current note */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -