hschumann2/TempleOS-Source-Code
0847
1 2#help_index "Snd/Music"3 4public class CMusicGlbls5{6 U8 *cur_song;7 CTask *cur_song_task;8 I64 octave;9 F64 note_len;10 U8 note_map[7];11 Bool mute;12 I64 meter_top,meter_bottom;13 F64 tempo,stacatto_factor;14 15 //If you wish to sync with a16 //note in a Play() string. 0 is the start17 I64 play_note_num;18 19 F64 tM_correction,last_Beat,last_tM;20} music={NULL,NULL,4,1.0,{0,2,3,5,7,8,10},FALSE,4,4,2.5,0.9,0,0,0,0};21 22#help_index "Snd/Music;Time/Seconds"23public F64 tM()24{//Time in seconds synced to music subsystem.25 return (cnts.jiffies+music.tM_correction)/JIFFY_FREQ;26}27 28public F64 Beat()29{//Time in music beats.30 F64 res,cur_tM;31 PUSHFD32 CLI33 if (mp_cnt>1)34 while (LBts(&sys_semas[SEMA_TMBEAT],0))35 PAUSE36 cur_tM=tM;37 res=music.last_Beat;38 if (music.tempo)39 res+=(cur_tM-music.last_tM)*music.tempo;40 music.last_tM=cur_tM;41 music.last_Beat=res;42 LBtr(&sys_semas[SEMA_TMBEAT],0);43 POPFD44 return res;45}46 47#help_index "Snd/Music"48U8 *MusicSetOctave(U8 *st)49{50 I64 ch;51 ch=*st++;52 while ('0'<=ch<='9') {53 music.octave=ch-'0';54 ch=*st++;55 }56 return --st;57}58 59U8 *MusicSetMeter(U8 *st)60{61 I64 ch;62 ch=*st++;63 while (ch=='M') {64 ch=*st++;65 if ('0'<=ch<='9') {66 music.meter_top=ch-'0';67 ch=*st++;68 }69 if (ch=='/')70 ch=*st++;71 if ('0'<=ch<='9') {72 music.meter_bottom=ch-'0';73 ch=*st++;74 }75 }76 return --st;77}78 79U8 *MusicSetNoteLen(U8 *st)80{81 Bool cont=TRUE;82 do {83 switch (*st++) {84 case 'w': music.note_len=4.0; break;85 case 'h': music.note_len=2.0; break;86 case 'q': music.note_len=1.0; break;87 case 'e': music.note_len=0.5; break;88 case 's': music.note_len=0.25; break;89 case 't': music.note_len=2.0*music.note_len/3.0; break;90 case '.': music.note_len=1.5*music.note_len; break;91 default:92 st--;93 cont=FALSE;94 }95 } while (cont);96 return st;97}98 99public U0 Play(U8 *st,U8 *words=NULL)100{/* Notes are entered with a capital letter.101 102Octaves are entered with a digit and103stay set until changed. Mid C is octave 4.104 105Durations are entered with106'w' whole note107'h' half note108'q' quarter note109'e' eighth note110't' sets to 2/3rds the current duration111'.' sets to 1.5 times the current duration112durations stay set until changed.113 114'(' tie, placed before the note to be extended115 116music.meter_top,music.meter_bottom is set with117"M3/4"118"M4/4"119etc.120 121Sharp and flat are done with '#' or 'b'.122 123The var music.stacatto_factor can124be set to a range from 0.0 to 1.0.125 126The var music.tempo is quarter-notes127per second. It defaults to1282.5 and gets faster when bigger.129*/130 U8 *word,*last_st;131 I64 note,octave,i=0,ona,timeout_val,timeout_val2;132 Bool tie;133 F64 d,on_jiffies,off_jiffies;134 music.play_note_num=0;135 while (*st) {136 timeout_val=cnts.jiffies;137 tie=FALSE;138 139 do {140 last_st=st;141 if (*st=='(') {142 tie=TRUE;143 st++;144 } else {145 st=MusicSetMeter(st);146 st=MusicSetOctave(st);147 st=MusicSetNoteLen(st);148 }149 } while (st!=last_st);150 151 if (!*st) break;152 note=*st++-'A';153 if (note<7) {154 note=music.note_map[note];155 octave=music.octave;156 if (*st=='b') {157 note--;158 if (note==2)159 octave--;160 st++;161 } else if (*st=='#') {162 note++;163 if (note==3)164 octave++;165 st++;166 }167 ona=Note2Ona(note,octave);168 } else169 ona=ONA_REST;170 if (words && (word=LstSub(i++,words)) && StrCmp(word," "))171 "%s",word;172 d=JIFFY_FREQ*music.note_len/music.tempo;173 if (tie) {174 on_jiffies =d;175 off_jiffies =0;176 } else {177 on_jiffies =d*music.stacatto_factor;178 off_jiffies =d*(1.0-music.stacatto_factor);179 }180 timeout_val+=on_jiffies;181 timeout_val2=timeout_val+off_jiffies;182 183 if (!music.mute)184 Snd(ona);185 SleepUntil(timeout_val);186 music.tM_correction+=on_jiffies-ToI64(on_jiffies);187 188 if (!music.mute)189 Snd;190 SleepUntil(timeout_val2);191 music.tM_correction+=off_jiffies-ToI64(off_jiffies);192 193 music.play_note_num++;194 }195}196 197U0 MusicSettingsRst()198{199 music.play_note_num=0;200 music.stacatto_factor=0.9;201 music.tempo=2.5;202 music.octave=4;203 music.note_len=1.0;204 music.meter_top=4;205 music.meter_bottom=4;206 SndRst;207 PUSHFD208 CLI209 if (mp_cnt>1)210 while (LBts(&sys_semas[SEMA_TMBEAT],0))211 PAUSE212 music.last_tM=tM;213 music.last_Beat=0.0;214 LBtr(&sys_semas[SEMA_TMBEAT],0);215 POPFD216}217 218MusicSettingsRst;219 220U0 CurSongTask()221{222 Fs->task_end_cb=&SndTaskEndCB;223 while (TRUE)224 Play(music.cur_song);225}226 