_cooper_ Posted October 9, 2017 Share Posted October 9, 2017 Hi ! I'm still going on doing stuff on my side with my Lynx, and i'm still playing around with ABCmusic for newcc65. I discovered each voice has a max length of 255 chars, including instruments configuration, which is quite tight to have a proper tune written I've found that Karri has put the sourcecode on bitbucket for abcmusic, available here (thanks Karri !) : https://bitbucket.org/atarilynx/lynx/src/f68a49d18f50df286a371caf4c75d21c51a4658b/contrib/abcmusic/newcc65version/abcmusic.m65?at=master&fileviewer=file-view-default I had a silly idea, but is it possible to bypass this 255 chars limit ? Pointing in a specific address in RAM, or adding a specific char detection in the pattern data which would jump to an other dc.b declaration ? (really ugly but perhaps easier to do ?) Unfortunately i have no asm knowledge to do this but perhaps some lynxdev wizards out there could give a hand ? I know the new compiler is out there but i know some of us still use the old version (for convenience reasons or lazyness ) Anyway any opinion is ofcourse welcome ! Quote Link to comment Share on other sites More sharing options...
LordKraken Posted October 9, 2017 Share Posted October 9, 2017 You have given up playing mod music? (well ok it works but it takes a bunch of memory, that's doable if you don't use the collision buffer), Quote Link to comment Share on other sites More sharing options...
_cooper_ Posted October 9, 2017 Author Share Posted October 9, 2017 no, but as u say, really memory hungry and too much stuff stored in ram already and i think ABCmusic is enough for many things if we can stretch the musicfile sizes Quote Link to comment Share on other sites More sharing options...
_cooper_ Posted October 11, 2017 Author Share Posted October 11, 2017 Sourcecode has been slightly modified to try to bypass the limit, but no sound for the moment Here is the code if somebody manage to catch a weird thing... ; ABC music definition file global _silence global _update_music global _abcmusic xref popax ; vars for ABC-music bsszp abc_score_ptr0 ds 2 abc_score_ptr1 ds 2 abc_score_ptr2 ds 2 abc_score_ptr3 ds 2 ; Pointer temporaires abc_score_ptr0_tmp ds 2 abc_score_ptr1_tmp ds 2 abc_score_ptr2_tmp ds 2 abc_score_ptr3_tmp ds 2 text abcsilence dc.b 0 ; Set all scores to silent at startup _silence:: lda #$00 sta $fd50 ; all channels to left+right lda #<abcsilence ldy #>abcsilence ldx #0 jsr _abc_set_score lda #<abcsilence ldy #>abcsilence ldx #1 jsr _abc_set_score lda #<abcsilence ldy #>abcsilence ldx #2 jsr _abc_set_score lda #<abcsilence ldy #>abcsilence ldx #3 jmp _abc_set_score abc_read_number:: stz abc_tmp stz abc_tmp+1 .tentimes1 jsr abc_read_char cmp #$2f bcc .tentimes9 cmp #$39 bcs .tentimes9 and #$0f pha lda abc_tmp clc rol sta abc_tmp clc rol clc rol bcc .tentimes2 inc abc_tmp+1 .tentimes2 clc adc abc_tmp bcc .tentimes3 inc abc_tmp+1 .tentimes3 sta abc_tmp pla clc adc abc_tmp bcc .tentimes4 inc abc_tmp+1 .tentimes4 sta abc_tmp bra .tentimes1 .tentimes9 dey lda abc_tmp rts _abcmusic:: jsr popax ; pop string sta abc_tmp stx abc_tmp+1 jsr popax ; pop channel tax lda abc_tmp ldy abc_tmp+1 ; Activate score on channel X ; A - low address ; Y - high address _abc_set_score:: inx dex bne .abc_set_score2 ldx sound_channel_busy bne .abc_set_score1 ; On met le ptr dans le temporaire sta abc_score_ptr0_tmp sta abc_score_ptr0 ; puis dans le slot de base sty abc_score_ptr0+1 stz abc_music_ptr stz sound_channel_duration .abc_set_score1 rts .abc_set_score2 dex bne .abc_set_score4 ldx sound_channel_busy+1 bne .abc_set_score3 sta abc_score_ptr1_tmp sta abc_score_ptr1 sty abc_score_ptr1+1 stz abc_music_ptr+1 stz sound_channel_duration+1 .abc_set_score3 rts .abc_set_score4 dex bne .abc_set_score6 ldx sound_channel_busy+2 bne .abc_set_score5 sta abc_score_ptr2_tmp sta abc_score_ptr2 sty abc_score_ptr2+1 stz abc_music_ptr+2 stz sound_channel_duration+2 .abc_set_score5 rts .abc_set_score6 ldx sound_channel_busy+3 bne .abc_set_score7 sta abc_score_ptr3_tmp sta abc_score_ptr3 sty abc_score_ptr3+1 stz abc_music_ptr+3 stz sound_channel_duration+3 .abc_set_score7 rts ;-------------------------------------------------------------- ; Once at each frame we can update the music ; You should call this routine frequently. ; Once in a frame is a good idea. _update_music:: ldx #0 update_channel_x: lda sound_channel_duration,x bne .update_music1 ; note has ended, fetch next lda abc_music_ptr,x tay bra parse_abc .update_music1 ; note is playing cmp #255 ; Duration 255 is forever, good for engines beq .update_music2 dea sta sound_channel_duration,x .update_music2 update_channel_tail: lda sound_channel_maxlen,x beq .update_music3 dea sta sound_channel_maxlen,x bne .update_music3 sta sound_channel_max_volume,x .update_music3 lda sound_channel_max_volume,x bne .update_music5 ; silence lda sound_channel_volume,x beq .update_music5 ; decay time still going on sec sbc abc_instrument_decr,x bcs .update_music4 ; silence lda #0 .update_music4 sta sound_channel_volume,x .update_music5 lda sound_channel_volume,x cmp sound_channel_max_volume,x bcs .update_music8 ; attack time clc adc abc_instrument_incr,x bcc .update_music6 ; desired volume reached lda sound_channel_max_volume,x .update_music6 cmp sound_channel_max_volume,x bcc .update_music7 beq .update_music7 ; desired volume reached lda sound_channel_max_volume,x .update_music7 sta sound_channel_volume,x .update_music8 lda sound_channel_volume,x phx pha txa clc rol clc rol clc rol tax pla sta $fd20,x plx inx txa cmp #4 bne update_channel_x rts ;-------------------------------------------------------------- ; Parse score enough to get next note ; X - channel to use ; Y - abc music pointer parse_abc:: jsr abc_read_char cmp #$0 ; End of music bne .parse_abc1 sta sound_channel_busy,x bra update_channel_tail .parse_abc1 cmp #$20 ;' ' ignore spaces bne .parse_abc2 bra parse_abc .parse_abc2 cmp #$7c ;'|' bne .parse_abc6 jsr abc_read_char cmp #$3a ;':' bne .parse_abc4 tya sta abc_repeat_offs,x lda #0 sta abc_repeat_cnt,x bra .parse_abc5 .parse_abc4 dey .parse_abc5 jmp parse_abc .parse_abc6 cmp #$3a ;':' bne .parse_abc7 phy lda abc_repeat_offs,x tay pla ;sta abc_repeat_offs,x jmp parse_abc .parse_abc7 cmp #$50 ;'P' priority - wait until sound has ended bne .parse_abc8u sta sound_channel_busy,x jmp parse_abc .parse_abc8u cmp #'V' ; volume bne .parse_abc8 jsr abc_read_number sta abc_note_volume,x jmp parse_abc .parse_abc8 cmp #'R' ; ramp up bne .parse_abc8a jsr abc_read_number sta abc_instrument_incr,x jmp parse_abc .parse_abc8a cmp #'H' ; hold bne .parse_abc8b jsr abc_read_number sta abc_instrument_maxlen,x jmp parse_abc .parse_abc8b cmp #'K' ; kill sound bne .parse_abc8c jsr abc_read_number sta abc_instrument_decr,x jmp parse_abc .parse_abc8c cmp #'I' ; incremental flag bne .parse_abc9 jsr abc_read_number phx txa clc rol clc rol clc rol tax lda abc_tmp cmp #0 bne .parse_abc8d lda $fd25,x and #$df bra .parse_abc8e .parse_abc8d lda $fd25,x ora #$20 .parse_abc8e ora #$18 sta $fd25,x plx jmp parse_abc .parse_abc9 cmp #$54 ;'T' tempo bne .parse_abc9b jsr abc_read_number sta abc_note_length,x jmp parse_abc .parse_abc9b cmp #$4f ;'O' octave bne .parse_abc9c jsr abc_read_number phx txa clc rol clc rol clc rol tax lda $fd25,x and #$f8 ora #$18 ora abc_tmp sta $fd25,x plx jmp parse_abc .parse_abc9c cmp #'X'; XOR taps bne .parse_abc10 jsr abc_read_number phx txa ; modify X to point to sound channel clc rol clc rol clc rol tax lda abc_tmp ; The two topmost bits are shifted one place right bpl .parse_abc9d ora #$40 bra .parse_abc9e .parse_abc9d and #$bf .parse_abc9e dec abc_tmp+1 beq .parse_abc9f and #$7f bra .parse_abc9g .parse_abc9f ora #$80 .parse_abc9g sta $fd21,x ; Bit $40 is put in a different register lda abc_tmp and #$40 bne .parse_abc9h lda $fd25,x and #$7f bra .parse_abc9i .parse_abc9h lda $fd25,x ora #$80 .parse_abc9i ora #$18 sta $fd25,x lda #0 sta $fd23,x plx jmp parse_abc .parse_abc10 cmp #$7a ;'z' bne .parse_abc11 lda #0 bra set_music_ptr .parse_abc11 ; Find out the pitch of the note stz cur_note inc cur_note cmp #$3d ;'=' bne .parse_abc12 inc cur_note jsr abc_read_char .parse_abc12 cmp #$7e ;'~' bne .parse_abc13 dec cur_note jsr abc_read_char .parse_abc13 sec sbc #$41 ;'A' cmp #8 ;'H'-'A' bcs .parse_abc14 ;_IFLO clc asl clc adc cur_note sta cur_note bra .parse_abc15 .parse_abc14 sec sbc #$20 ;'a'-'A' + 15 clc asl clc adc cur_note clc adc #15 sta cur_note .parse_abc15 lda cur_note phy tay lda _delays,y phx pha txa clc rol clc rol clc rol tax pla sta $fd24,x plx ply ; Find out the volume of the note lda abc_note_volume,x set_music_ptr: sta sound_channel_max_volume,x ; Find out the duration of the note jsr abc_read_char cmp #$34 ; "4" bne .parse_abc16 lda abc_note_length,x clc rol clc rol bra .parse_abc19 .parse_abc16 cmp #$33 ; "3" bne .parse_abc17 lda abc_note_length,x clc rol clc adc abc_note_length,x bra .parse_abc19 .parse_abc17 cmp #$32 ; "2" bne .parse_abc18 lda abc_note_length,x clc rol bra .parse_abc19 .parse_abc18 dey lda abc_note_length,x .parse_abc19 sta sound_channel_duration,x tya sta abc_music_ptr,x lda abc_instrument_maxlen,x sta sound_channel_maxlen,x jmp update_channel_x ;-------------------------------------------------------------- ; This table is used to cover the delays needed for 2 octaves _delays dc.b 161 ; Ab dc.b 152 ; A dc.b 143 ; A# Bb dc.b 135 ; B dc.b 128 ; dc.b 255 ; C dc.b 241 ; C# Db dc.b 227 ; D dc.b 214 ; D# Eb dc.b 202 ; E dc.b 191 ; dc.b 191 ; F dc.b 180 ; F# Gb dc.b 170 ; G dc.b 161 ; G# _delays2 dc.b 80 ; ab dc.b 76 ; a dc.b 72 ; a# bb dc.b 68 ; b dc.b 128 ; dc.b 128 ; c dc.b 120 ; c# db dc.b 114 ; d dc.b 107 ; d# eb dc.b 101 ; e dc.b 96 ; dc.b 96 ; f dc.b 90 ; f# gb dc.b 85 ; g dc.b 80 ; g# ;-------------------------------------------------------------- ; Read a character from the score. Advance ptr if it is not 0 ; X - channel ; Y - score offset abc_read_char:: txa ina dea bne .abc_read_char1 ; lda (abc_score_ptr0),y lda (abc_score_ptr0_tmp) inc abc_score_ptr0_tmp ; Augmente de 1 bra .abc_read_char4 .abc_read_char1 dea bne .abc_read_char2 ;lda (abc_score_ptr1),y lda (abc_score_ptr1_tmp) inc abc_score_ptr1_tmp ; Augmente de 1 bra .abc_read_char4 .abc_read_char2 dea bne .abc_read_char3 ;lda (abc_score_ptr2),y lda (abc_score_ptr2_tmp) inc abc_score_ptr2_tmp ; Augmente de 1 bra .abc_read_char4 .abc_read_char3 ; lda (abc_score_ptr3),y lda (abc_score_ptr3_tmp) inc abc_score_ptr3_tmp ; Augmente de 1 .abc_read_char4 beq .abc_read_char5 iny .abc_read_char5 rts ;-------------------------------------------------------------- ; Instrument setup. C-interface _abcinstrument:: ; Lynx-specific abc-command to set up the instrument jsr popax ; channel sta instrumenttmp+1 clc rol clc rol clc rol sta instrumenttmp jsr popax ; shift 012345 10 11 ldx instrumenttmp sta $fd21,x jsr popax ; start value not needed ldx instrumenttmp+1 sta abc_note_length,x ldx instrumenttmp ; sta $fd23,x jsr popax ; backup not needed ldx instrumenttmp+1 sta abc_note_volume,x ldx instrumenttmp ; sta $fd24,x jsr popax ; flags b012 clock b5 integr b7 fb7 ldx instrumenttmp sta $fd25,x jsr popax ; attack ldx instrumenttmp+1 sta abc_instrument_incr,x jsr popax ; hold ldx instrumenttmp+1 sta abc_instrument_maxlen,x jsr popax ; decay ldx instrumenttmp+1 sta abc_instrument_decr,x rts instrumenttmp ds 2 abc_music_ptr dc.b 0,0,0,0 abc_repeat_offs dc.b 0,0,0,0 abc_repeat_cnt dc.b 0,0,0,0 abc_note_length dc.b 6,6,6,6 abc_note_volume dc.b 64,64,64,64 abc_instrument_incr dc.b 4,4,4,4 abc_instrument_maxlen dc.b 4,4,4,4 abc_instrument_decr dc.b 4,4,4,4 sound_channel_busy dc.b 0,0,0,0 sound_channel_max_volume dc.b 60,127,127,127 sound_channel_volume dc.b 4,4,4,4 sound_channel_maxlen dc.b 4,4,4,4 sound_channel_duration dc.b 0,0,0,0 cur_note dc.b 0 abc_tmp ds 2 Quote Link to comment Share on other sites More sharing options...
_cooper_ Posted October 15, 2017 Author Share Posted October 15, 2017 Music size problem solved, only some looping probs remaining... stay tuned !! Quote Link to comment Share on other sites More sharing options...
LordKraken Posted October 16, 2017 Share Posted October 16, 2017 If you provide an updated version of the library I'll take one Quote Link to comment Share on other sites More sharing options...
+karri Posted October 16, 2017 Share Posted October 16, 2017 I would also very much like patches to improve on this library. The reason I abandoned it was that the music was out of tune and I did not find out why. Quote Link to comment Share on other sites More sharing options...
_cooper_ Posted October 16, 2017 Author Share Posted October 16, 2017 nah i'll keep all for myself Seriously, it will be of course available for everybody when finished. Im confident that the asm wizard looking into this code will kill the last remaining bugs Quote Link to comment Share on other sites More sharing options...
+karri Posted November 10, 2017 Share Posted November 10, 2017 I had a need for abcmusic myself. So I fixed the in-tune issues in the pure c version. The cversion can also play longer tunes than 256 bytes. Quote Link to comment Share on other sites More sharing options...
LordKraken Posted November 10, 2017 Share Posted November 10, 2017 Any chance this would compile with newcc65? (yeah I know we are quite stubborn Quote Link to comment Share on other sites More sharing options...
+karri Posted November 10, 2017 Share Posted November 10, 2017 I assume that it could be made to work. But it has to wait until I am back in Finland. Currently enjoying some dancing in Croatia and I only have a small tablet with me. Quote Link to comment Share on other sites More sharing options...
Turbo Laser Lynx Posted November 11, 2017 Share Posted November 11, 2017 Really nice that there's stuff going on with abc-music! (I always liked it) : > I guess the 'pure C fix' is for the newest cc65 that You've been working on Karri? I downloaded the files already but I haven't tried it yet. Quote Link to comment Share on other sites More sharing options...
+karri Posted December 8, 2017 Share Posted December 8, 2017 (edited) The novel development kicked off some new features in the pure C variant of the ABC module. I plan to write some instructions of how to use it. The cc65 variant was also fixed but as it it interrupt driven I did not want to run it in the same cart with Chipper. The Reiko's Robot Run was Chipper based. But the cc65 can handle long abc tunes. So there is no 256 byte limitations. I am also adding a digitized sound api running at HBL interrupt rate. The HBL interrupts occur at 105 x frame rate. So ABC music could use frame rate for notes and scan line rate divided by two for digitized sound like speech. The quality is pretty good at 4kHz. The tests to run fake arpeggio chords did not turn out well. So doing [CEG] won't work. I may write a python script to lynxify any abc tune. I added small test setups to different abcmusic directories to get sound out by just typing "make". Edited December 8, 2017 by karri Quote Link to comment Share on other sites More sharing options...
Turbo Laser Lynx Posted December 9, 2017 Share Posted December 9, 2017 (edited) So there is no 256 byte limitations. Nice, if you'd want to do something bigger! I am also adding a digitized sound api running at HBL interrupt rate. The HBL interrupts occur at 105 x frame rate. So ABC music could use frame rate for notes and scan line rate divided by two for digitized sound like speech. The quality is pretty good at 4kHz. That's really exciting! I love that stuff in for example APB. Opens up new possibilities in Lynx games. The tests to run fake arpeggio chords did not turn out well. So doing [CEG] won't work. Ah, too bad! I'm still second guessing myself if those fake-chords used on many 8-bit game systems and computers are the actual sounds or if they really are arpeggios (although I was told they are on another forum). I mean some of the chipper sounds I used in Reiko sounds like they're 'vibrating' back and forth between at least two notes (and those are only one note in the tracker). https://youtu.be/Yx6iY0BGHac?t=35s I added small test setups to different abcmusic directories to get sound out by just typing "make". Cool! Edited December 9, 2017 by Turbo Laser Lynx Quote Link to comment Share on other sites More sharing options...
Turbo Laser Lynx Posted October 3, 2018 Share Posted October 3, 2018 (edited) @Karri, a couple of questions about the old Lynx-native sound-finder program you had made if I may? The sounds generated with it didn't seem to be out of tune from each other? At least I remember experimenting and using whatever sounds from it in abc-music and the sounds were working fine together. Would there be a sensible way to translate sounds from the abc-sound-finder to chipper? It would speed up finding decent sounds a lot. I guess the sound-tool limits the "soundscape of the Lynx" since the sounds were not out of tune? But that would be a totally ok trade off since finding and creating sounds with it was much easier than with chipper. Your chipper sound collection and chipper example songs (with sounds) is a nice start though. Edited October 3, 2018 by Turbo Laser Lynx Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.