U0 PsmNoteDel(PsmNote *tmpn) { Free(tmpn->word); Free(tmpn); } PsmNote *PsmNoteCopy(PsmNote *tmpn) { PsmNote *tmpn1=MAllocIdent(tmpn); if (tmpn->word) tmpn1->word=StrNew(tmpn->word); else tmpn1->word=NULL; return tmpn1; } U0 PsmSongDel(PsmNote *head) { PsmNote *tmpn,*tmpn1; tmpn=head->next; while (tmpn!=head) { tmpn1=tmpn->next; PsmNoteDel(tmpn); tmpn=tmpn1; } QueInit(head); } U0 PsmCutToClip() { PsmNote *tmpn,*tmpn1; PsmSongDel(&psm.clip); tmpn=psm.head.next; while (tmpn!=&psm.head) { tmpn1=tmpn->next; if (tmpn->flags&PSMF_SEL) { if (psm.cur_note==tmpn) psm.cur_note=tmpn->next; QueRem(tmpn); tmpn->flags&=~PSMF_SEL; QueIns(tmpn,psm.clip.last); } tmpn=tmpn1; } } U0 PsmPasteClip() { PsmNote *tmpn,*tmpn1; tmpn=psm.clip.next; while (tmpn!=&psm.clip) { tmpn1=PsmNoteCopy(tmpn); QueIns(tmpn1,psm.cur_note->last); tmpn=tmpn->next; } } U0 PsmCopyToClip() { PsmNote *tmpn,*tmpn1; PsmSongDel(&psm.clip); tmpn=psm.head.next; while (tmpn!=&psm.head) { if (tmpn->flags&PSMF_SEL) { tmpn->flags&=~PSMF_SEL; tmpn1=PsmNoteCopy(tmpn); QueIns(tmpn1,psm.clip.last); } tmpn=tmpn->next; } } PsmNote *PsmFindNote(I64 x,I64) { PsmNote *tmpn=psm.head.next; PsmRecalcNoteXY; x+=PSM_NOTE_SPACING/2; while (x>tmpn->next->x && tmpn!=&psm.head) tmpn=tmpn->next; return tmpn; } U8 *PsmMusicSetOctave(U8 *st,I64 *psm_octave) { while ('0'<=*st<='9') *psm_octave=*st++ -'0'; return st; } U8 *PsmMusicSetNoteLen(U8 *st,F64 *psm_duration) { Bool cont=TRUE; do { switch (*st++) { case 'w': *psm_duration=4.0; break; case 'h': *psm_duration=2.0; break; case 'q': *psm_duration=1.0; break; case 'e': *psm_duration=0.5; break; case 's': *psm_duration=0.25; break; case 't': *psm_duration=2.0* *psm_duration/3.0; break; case '.': *psm_duration=1.5* *psm_duration; break; default: st--; cont=FALSE; } } while (cont); return st; } U0 PsmLoadSongStr(U8 *st,I64 *psm_octave,F64 *psm_duration) { PsmNote *tmpn,*tmpn1; I64 note,i=0; while (*st) { tmpn=CAlloc(sizeof(PsmNote)); while (*st && !('A'<=*st<='G') && *st!='R') { if (*st=='M') { tmpn1=CAlloc(sizeof(PsmNote)); tmpn1->type=PSMT_METER; st++; if ('1'<=*st<='9') tmpn1->meter_top=*st++-'0'; else tmpn1->meter_top=4; if (*st=='/') st++; if ('1'<=*st<='9') tmpn1->meter_bottom=*st++-'0'; else tmpn1->meter_bottom=4; PsmSetWidth(tmpn1); QueIns(tmpn1,psm.head.last); } while (*st=='(') { Bts(&tmpn->flags,PSMf_TIE); st++; } st=PsmMusicSetOctave(st,psm_octave); st=PsmMusicSetNoteLen(st,psm_duration); } if (!*st) { PsmNoteDel(tmpn); break; } note=*st++-'A'; if (note<7) { note=music.note_map[note]; if (*st=='b') { Bts(&tmpn->flags,PSMf_FLAT); note--; st++; if (note<0) //Ab note=11; else if (note==2) //Cb *psm_octave-=1; } else if (*st=='#') { Bts(&tmpn->flags,PSMf_SHARP); note++; st++; if (note>11) //G# note=0; else if (note==3) //B# *psm_octave+=1; } tmpn->ona=Note2Ona(note,*psm_octave); } else tmpn->ona=ONA_REST; if (*psm_duration<=2*.25/3) i=0; else if (*psm_duration<=.25) i=1; else if (*psm_duration<=2*.5/3) i=2; else if (*psm_duration<=.5) i=3; else if (*psm_duration<=2.0/3) i=4; else if (*psm_duration<=.5*1.5) i=5; else if (*psm_duration<=1.0) i=6; else if (*psm_duration<=1.5) i=7; else if (*psm_duration<=2.0) i=8; else if (*psm_duration<=3.0) i=9; else if (*psm_duration<=4.0) i=10; else i=11; tmpn->duration=i; tmpn->type=PSMT_NOTE; PsmSetWidth(tmpn); QueIns(tmpn,psm.cur_note->last); } } U0 PsmLoadSong(U8 *filename,I64 *psm_octave,F64 *psm_duration) { U8 *st; PsmNote *tmpn; CCmpCtrl *cc=CmpCtrlNew(MStrPrint("#include \"%s\"",filename)); if (FileOcc("incomplete",filename,"")) psm.incomplete_entry->checked=TRUE; else psm.incomplete_entry->checked=FALSE; while (Lex(cc)) { if (cc->token==TK_IDENT) if (!StrCmp(cc->cur_str,"Play")) { if (Lex(cc)=='(') if (Lex(cc)==TK_STR) { tmpn=psm.head.last; st=LexExtStr(cc); PsmLoadSongStr(st,psm_octave,psm_duration); if (cc->token==',') { if (Lex(cc)==TK_STR) { st=LexExtStr(cc); do { do tmpn=tmpn->next; while (tmpn!=&psm.head && tmpn->type==PSMT_METER); if (tmpn!=&psm.head) tmpn->word=StrNew(st); st+=StrLen(st)+1; } while (*st); } } } } else if (!StrCmp(cc->cur_str,"music") && Lex(cc)=='.' && Lex(cc)==TK_IDENT) { if (!StrCmp(cc->cur_str,"tempo")) { if (Lex(cc)=='=' && Lex(cc)==TK_F64) { music.tempo=cc->cur_f64-0.0005; tempo_state.tempo=Round(TEMPO_RANGE*(music.tempo-0.5)/4.4); } } else if (!StrCmp(cc->cur_str,"stacatto_factor")) { if (Lex(cc)=='=' && Lex(cc)==TK_F64) { music.stacatto_factor=cc->cur_f64-0.0005; tempo_state.stacatto= Round(TEMPO_RANGE*(music.stacatto_factor-0.12)/0.88); } } } } CmpCtrlDel(cc); } U8 *PsmCvtSong() { PsmNote *tmpn; U8 *st,*src,*dst; I64 i,ona,note,octave,last_octave,last_duration; i=0; tmpn=psm.head.next; last_octave=I64_MIN; last_duration=-1; while (tmpn!=&psm.head) { dst=&tmpn->ascii; if (tmpn->type==PSMT_METER) { *dst++='M'; *dst++=tmpn->meter_top+'0'; *dst++='/'; *dst++=tmpn->meter_bottom+'0'; } else { if (tmpn->ona!=ONA_REST) { ona=tmpn->ona; if (Bt(&tmpn->flags,PSMf_SHARP)) ona--; if (Bt(&tmpn->flags,PSMf_FLAT)) ona++; octave=Ona2Octave(ona); note =Ona2Note (ona); note=music.note_map[*LstSub(note,psm_note_lst)-'A']; } if (Bt(&tmpn->flags,PSMf_TIE)) *dst++='('; if (octave!=last_octave && tmpn->ona!=ONA_REST) { *dst++=octave+'0'; last_octave=octave; } if (tmpn->duration!=last_duration) { src=LstSub(tmpn->duration,psm_duration_lst); *dst++=src[0]; if (src[1]) *dst++=src[1]; last_duration=tmpn->duration; } if (tmpn->ona!=ONA_REST) { src=LstSub(note,psm_note_lst); *dst++=src[0]; if (src[1]) *dst++=src[1]; else if (Bt(&tmpn->flags,PSMf_FLAT)) *dst++='b'; else if (Bt(&tmpn->flags,PSMf_SHARP)) *dst++='#'; } else *dst++='R'; } *dst++=0; i+=StrLen(tmpn->ascii); tmpn=tmpn->next; } st=MAlloc(i+1); dst=st; tmpn=psm.head.next; while (tmpn!=&psm.head) { StrCpy(dst,tmpn->ascii); dst+=StrLen(tmpn->ascii); tmpn=tmpn->next; } *dst++=0; return st; } U8 *PsmSaveSong(U8 *dirname,U8 *full_filename) { CDoc *doc=DocNew(full_filename); Bool has_words; PsmNote *tmpn,*tmpn1; F64 measure_len=4,two_measure_left=2*measure_len; I64 ch; U8 *ptr; Free(PsmCvtSong); //set tmpn->ascii; music.tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5; music.stacatto_factor=0.88*tempo_state.stacatto/TEMPO_RANGE+0.12; has_words=FALSE; tmpn=psm.head.next; while (tmpn!=&psm.head) { if (PsmHasWords(tmpn->word)) has_words=TRUE; tmpn=tmpn->next; } if (psm.incomplete_entry->checked) DocPrint(doc,"//0 incomplete\n"); else if (has_words) DocPrint(doc,"//0 has words\n"); else DocPrint(doc,"//0 no nothing\n"); DocPrint(doc, "U0 Song()\n" "{\n" " Fs->task_end_cb=&SndTaskEndCB;\n" " MusicSettingsRst;\n" " music.tempo=%6.3f;\n" " music.stacatto_factor=%6.3f;\n" " try {\n" " while (!ScanKey) {\n" "\tPlay(\"",music.tempo+0.0005,music.stacatto_factor+0.0005); tmpn=psm.head.next; tmpn1=tmpn; has_words=FALSE; while (tmpn!=&psm.head) { DocPrint(doc,"%s",tmpn->ascii); if (PsmHasWords(tmpn->word)) has_words=TRUE; if (tmpn->type==PSMT_METER) { measure_len=tmpn->meter_top*4.0/tmpn->meter_bottom; two_measure_left=0; } else two_measure_left-=psm_durations[tmpn->duration]; tmpn=tmpn->next; if (two_measure_left<0.001 && tmpn!=&psm.head) { if (has_words) { DocPrint(doc,"\",\n\t\t\""); while (tmpn1!=tmpn) { if (tmpn1->type!=PSMT_METER) { if (ptr=tmpn1->word) { while (ch=*ptr) { if (ch==CH_SPACE) *ptr=CH_SHIFT_SPACE; ptr++; } DocPrint(doc,"%Q\\0",tmpn1->word); } else DocPrint(doc,"%c\\0",CH_SHIFT_SPACE); } tmpn1=tmpn1->next; } } DocPrint(doc,"\");\n" "\tPlay(\""); two_measure_left=2*measure_len; tmpn1=tmpn; has_words=FALSE; } } if (has_words) { DocPrint(doc,"\",\n\t\t\""); while (tmpn1!=tmpn) { if (tmpn1->type!=PSMT_METER) { if (ptr=tmpn1->word) { while (ch=*ptr) { if (ch==CH_SPACE) *ptr=CH_SHIFT_SPACE; ptr++; } DocPrint(doc,"%Q\\0",tmpn1->word); } else DocPrint(doc,"%c\\0",CH_SHIFT_SPACE); } tmpn1=tmpn1->next; } } DocPrint(doc,"\");\n" " }\n" " } catch\n" " PutExcept;\n" " Snd;\n" "}\n" "\n" "Song;\n"); DocRecalc(doc); if (full_filename) Free(full_filename); else StrPrint(doc->filename.name,"%s/Tmp.HC.Z",dirname); DocWrite(doc,TRUE); full_filename=StrNew(doc->filename.name); DocDel(doc); return full_filename; }