Trivial Solutions
                    The LoseThos 64-bit PC Operating System
File:/LT/Adam/Snd/Music.APZ
This, and all LoseThos files, are public domain.  Do whatever you like.
God is watching; God is just; God is never out-done in generosity.  He talks!

LoseThos code compiles with the 64-bit LoseThos compiler/assembler I wrote.
Boot the LoseThos CD and you can compile it.  Not in Kansas anymore!

Click here for preliminary compiler information you need.

#help_index "Snd/Music"
U8 *cur_song=NULL;
TaskStruct *cur_song_task=NULL;
U64 music_octave;
F64 music_note_len;
U8 music_note_map[7]={0,2,3,5,7,8,10};
I64 music_mute=0;
I64 music_waveform,music_meter_top,music_meter_bottom;

//This is if you wish to sync with a
//note in a Play() string.  0 is the start
public I64 music_play_note_num=0;

public F64 music_tempo,music_stacatto_factor,music_amplitude;

U8 *MusicSetOctave(U8 *st)
{
  U8 ch=*st++;
  while ('0'<=ch<='9') {
    music_octave=ch-'0';
    ch=*st++;
  }
  return --st;
}

U8 *MusicSetWaveform(U8 *st)
{
  U8 ch=*st++;
  while (ch=='W') {
    ch=*st++;
    if ('0'<=ch<'0'+WF_NUM_WAVEFORMS) {
      music_waveform=ch-'0';
      ch=*st++;
    }
  }
  return --st;
}

U8 *MusicSetMeter(U8 *st)
{
  U8 ch=*st++;
  while (ch=='M') {
    ch=*st++;
    if ('0'<=ch<='9') {
      music_meter_top=ch-'0';
      ch=*st++;
    }
    if (ch=='/')
      ch=*st++;
    if ('0'<=ch<='9') {
      music_meter_bottom=ch-'0';
      ch=*st++;
    }
  }
  return --st;
}

U8 *MusicSetNoteLen(U8 *st)
{
  BoolI8 cont=TRUE;
  do {
    switch (*st++) {
      case 'w': music_note_len=4.0;  break;
      case 'h': music_note_len=2.0;  break;
      case 'q': music_note_len=1.0;  break;
      case 'e': music_note_len=0.5;   break;
      case 's': music_note_len=0.25;   break;
      case 't': music_note_len=2.0*music_note_len/3.0; break;
      case '.': music_note_len=1.5*music_note_len; break;
      default:
        st--;
        cont=FALSE;
    }
  } while (cont);
  return st;
}

public U0 Play(U8 *st,U8 *words=NULL)
/*
  Notes are entered with a capital letter.

  Octaves are entered with a digit and
  stay set until changed.

  Durations are entered with
    'w' whole note
    'h' half note
    'q' quarter note
    'e' eighth note
    't' sets to 2/3rds the current duration
    '.' sets to 1.5 times the current duration
  durations stay set until changed.

  Accents are made with
    '!'   *1.5
    '!!'  *1.5`2

  music_waveform is set with
    "W1" for WF_SQUARE
    "W2" for WF_SINE
    "W3" for WF_TRIANGLE
    "W4" for WF_SAWTOOTH
    "W5" for WF_NOISE

  music_meter_top,music_meter_bottom is set with
    "M3/4"
    "M4/4"
    etc.

  Sharp and flat are done with '#' or 'b'.

  The var music_stacatto_factor can
  be set to a range from 0.0 to 1.0.

  The var music_amplitude can
  be set to a range from 0.0 to 1.0.

  The var music_tempo is quarter-notes
  per second.  It defaults to
  2.5 and gets faster when bigger.
 
*/

{
  U8 *word;
  U64 note,i=0,timeout_val,timeout_val2;
  BoolI8 old_preempt=Preempt(OFF);
  F64 f,d,a;
  music_play_note_num=0;
  while (*st) {
    timeout_val=sys_jiffies;
    a=music_amplitude;

    while (*st && !('A'<=*st<='G') && *st!='R') {
      if (*st=='!') {
        a*=1.5;
        st++;
      } else {
        st=MusicSetWaveform(st);
        st=MusicSetMeter(st);
        st=MusicSetOctave(st);
        st=MusicSetNoteLen(st);
      }
    }
    if (!*st) break;
    note=*st++-'A';
    if (note<7) {
      note=music_note_map[note];
      if (*st=='b') {
        note--;
        st++;
      } else if (*st=='#') {
        note++;
        st++;
      }
      f=Note2Freq(note,music_octave);
    } else
      f=0;
    if (words) {
      if (word=ListEntryPoint(i++,words))
        if (StrCmp(word," "))
          PutS(word);
    }

    d=JIFFY_FREQ*music_note_len/music_tempo;
    timeout_val+=d*music_stacatto_factor;
    timeout_val2=timeout_val+
      d*(1.0-music_stacatto_factor);

    if (!music_mute)
      Snd(f,music_waveform,a);
    SleepUntil(timeout_val);
    if (!music_mute)
      Snd(0,music_waveform,a);
    SleepUntil(timeout_val2);
    music_play_note_num++;
  }
  Preempt(old_preempt);
}

U0 MusicSettingsRst()
{
  music_play_note_num=0;
  music_stacatto_factor=0.9;
  music_amplitude=1/1.5`2;
  music_tempo=2.5;
  music_octave=3;
  music_note_len=1.0;
  music_waveform=WF_SQUARE;
  music_meter_top=4;
  music_meter_bottom=4;
  snd_reverb_intensity=0.2;
  snd_reverb_delay=0.3;
}

MusicSettingsRst;

U0 CurSongTask()
{
  Preempt(ON);
  Fs->task_end_cb=&SndTaskEndCB;
  while (TRUE)
    Play(cur_song);
}
#help_index "Snd"
Historical capture: 2011-11-26. Home | Power on LoseThos | Sources and changes