friedric@unipas.fmi.uni-passau.de (Carsten Friedrich) (05/08/91)
; Hi, ; as i got many, many requests about the source-code to play digitized ; music, i decided to post it instead of mailing to everyone. ; don't be confused by the letter like style, cos i just post the ; letter i've written to the first ones. ; I DIDN'T WRITE THE SOURCE, BUT TOOK IT FROM A ST-MAGAZINE ARTICLE AND ; CHANGED IT TO FIT MY NEEDS !!! (just wanted to make this clear) ; here's the promised source-code. It is NO executable program, but to ; be compiled as an object file and linked to a C-program. ; How to use it from a C-program: ; if you want to play a sample: ; set smp_anf_ to the begining of the sound-data. ; set smp_len_ to the length of the sound-data. ; set smp_frq_ to the playing frequenzy (0 to 30.000 in Hz) ; set smp_out_ to the scan-code of the character you want to abort playing ; before the end has been reached ; set smp_way_ to 1 if you want to play forward, any other value, if want ; to play the sample reverse (really funny flag) ; set smp_mod_ to 2 for playing samples ; start with start1(); ; you don't have to set 'em all, just look at the default values at the end ; of the listing. ; if you want to listen to a digitizer: ; set smp_mod_ to 0 for listening ; set smp_frq_ see above ; set smp_out_ escape character (SCAN-CODE!!!). IMPORTANT: no exit from this ; mode with an wrong scan-code !!!! only way then is reset-button ; then start1(); ; if you want to record samples ; set smp_mod_ to 1 ; set smp_frq_ to the frequenzy you want to sample with (0 to 20.000 in Hz) ; set smp_anf_ begining of sample-buffer ; set smp_end_ end of sample-buffer ; set smp_out_ see above. program terminates as well if reaching smp_end_ ; then start1(); ; in return smp_len_ is set by the program to the really sampled length ; If using a digitizer, it should be at the printer-port! ; I hope all this above is true, as wrote it more then 1 year ago, but ; you should be able to correct it by looking at the code. ; I'm not shure about copyrights, as I took a computer-magazine-article ; about a self-made sampler, and adapted their source to fit my needs. ; If they don't have the copyrights, then the rights are by me. You may ; copy it, adapt it, delete it, throw it a you're brothers head, or do what ; ever you want with it, but don't blame me for the results. ; It would be nice, if using it in a program, to insert the names Martin ; Backschat (the original author) or/and Carsten Friedrich (me :) . ; this program is written for the Devpack assembler, so you might have ; to change some lines for other assemblers. (e.g. dc.l to .dc.l) ; the program can play 8-bit samples (should be standart), but only uses ; 6-Bit, because i only have a 6-Bit sound-data-table :(. If you get hold ; of an 8-Bit table, i made a mark in the source, what you would have to ; change. (and please mail it to me .... :) ) ; although working with interupts, this program always (no matter what ; smp_frq_ ) uses 100 % CPU-time. This was made to improve speed and with ; that to improve sound-quality. I made a mark in the source, with some ; hints how to change that. but smp_frq_ should not exceed 20.000 Hz when ; doing this and if you want the computer to have the time, really to work ; while playing 10.000 Hz is a kind of limit. (Remember real sound-frequenzy ; is 0.5 * sample-frequenzy !, this means setting smp_frq to 10.000 Hz means ; a real sound of 5.000 Hz ) ; The program uses Timer D for interupt. If you want to uses RS232, you ; should change this to Timer A. I used Timer D, as I needed Timer A for ; more important things. ; I hope that helps you. Lables might be a bit confusing for you, as i named ; them in german. ; if using Devpack, you should be able to assemble it just as it is. ; sorry, just noticed, that it is executable, just remove the line XDEF. ; you should just add Pterm0 (gemdos(0)) if you don't like it to terminate ; with two bombs at the end, then assemble it as an executable program (*.tos) ; and you can listen to a sampler, if one is connected to the printer-port. ; to stop press space :) ; if you still have questions, or it just doesn't work, mail me and I'll try ; to help you. If you send me some money for stamps, I can send you the ; source listing of Martin Bachschat (it's a complete assemler program to deal ; with samplers at the printer port ca. 900 lines). If you send me a disc, I ; can copy the source-code and executable-code of a C-program I wrote for ; sampling and playing samples with the MarkWilliams C-compiler. It uses ; this assembler program for handling the sampler and sound out-put. I don't ; e-mail it, as it includes a .rsc file. But PLEASE don't forget to add some ; money for stamps and a disc, if you want my program. ; greetings, ; Carsten ! ; adress: ; Carsten Friedrich ; Machthildstr. 42 ; 8400 Regensburg ; W-Germany ; The source: XDEF start1_,smp_anf_,smp_end_,smp_frq_,smp_mod_,smp_out_,smp_len_,smp_way_ opt d+ start1_: ; movem.l d0-d7/a0-a7,jaja save registers clr.l -(sp) move.w #$20,-(sp) trap #1 addq.l #6,sp move.l d0,oldsp enter supervisor-mode ; pea siditab move.w #$20,-(sp) trap #$e addq.l #6,sp ; move.l #1000000,d0 test1: nop nop nop dbf d0,test1 initialise sound-chip and wait some time ; waiting is important ! moveq.l #0,d0 move.w smp_mod_,d0 cmp.w #2,d0 beq.s weit ; moveq.l #0,d0 moveq.l #0,d2 move.b smp_out_,d0 move.w smp_frq_,d1 move.w smp_mod_,d2 move.l smp_anf_,a1 move.l smp_end_,a2 bsr input for background-interupt do sndinit now, use bra weiter inputloop for interupt at $110, remove inpsync, weit: ; change inputloop and inpend to rte at the end moveq.l #0,d0 and not to loop. AND: SAVE REGISTERS whenstaring moveq.l #0,d2 inputloop, and restore before rte, and change sndinit move.b smp_out_,d0 to allow interupts, always refresh your own registers, move.w smp_frq_,d1 and no other sound during this time, and don't use discs move.w smp_way_,d2 (may cause loss of data), and don't try to print move.l smp_anf_,a1 (might kill the sound-chip, no kidding !!!!) move.l smp_len_,a2 if just playing samples, printing should be save add.l a1,a2 NO WARRANTY !!!! bsr play weiter: ; decide wich mode, set registers and enter move.l oldsp,-(sp) move.w #$20,-(sp) trap #1 addq.l #6,sp exit supervisor-mode movem.l jaja,d0-d7/a0-a7 restore registers rts back !!! input: bsr sndinit do some initialising work ; move.b #$e,(a5) move.b (a5),d7 or.b #$20,d7 move.b d7,2(a5) move.b #7,(a5) move.b (a5),d7 and.b #$7f,d7 move.b d7,2(a5) awake sampler and tell him we're ready ; should work with all samplers for the st inploop: moveq.l #0,d6 move.b #$f,(a5) move.b (a5),d6 get sound-data to d6 ; move.b #$e,(a5) and.b #$df,2(a5) or.b #$20,2(a5) tell sampler: sample next please ; tst.w d2 beq.s norec move.b d6,(a1)+ cmp.l a1,a2 beq.s inpend if recording, store data ; norec: and.b #%11111100,d6 mask off last 2 bits (we're only using 6-Bit) move.w d6,d7 add.w d6,d7 add.w d6,d7 get adress of data in sound-table. for 8-Bit movem.l 0(a3,d7),d5-d7 don't mask and change the get-adress-algorithm movem.l d5-d7,(a5) put data to sound-chip ; cmp.b 2(a4),d0 escape-character pressed ? beq.s inpend yes, then end inpsync: btst #4,$d(a6) beq.s inpsync waiting for the interupt bclr #4,$d(a6) restart interupt bra inploop next round ; inpend: tst.w d2 did we record? beq.s inpend2 sub.l smp_anf_,a1 move.l a1,smp_len_ yes, then evaluate smp_len_ and store it ; inpend2: bra sndinit2 restore things and return sndinit: move.w #$2700,sr disable all interupts lea voldat,a3 move.w #$fc00,a4 move.w #$8800,a5 move.w #$fa00,a6 load some registers ; move.l #2456700,d7 divu d1,d7 lsr.w #2,d7 move.b d7,$25(a6) move.b $1d(a6),d7 and.b #$f0,d7 or.b #$01,d7 move.b d7,$1d(a6) bset #4,9(a6) evaluate frequenzy to timer data and start interupt rts sndinit2: move.b $1d(a6),d7 and.b #$f0,d7 move.b d7,$1d(a6) bclr #4,9(a6) stop interupt move.w #$2300,sr allow interupts rts return play: bsr sndinit init-work moveq.l #0,d4 playloop: cmp.w #1,d2 beq play_v forward or backward? move.b -(a2),d4 cmp.l a1,a2 beq playend look if reached the end bra play_n play_v: move.b (a1)+,d4 cmp.l a1,a2 beq playend look if reached the end play_n: ; load next sound to play to d4 and.b #%11111100,d4 move.w d4,d7 add.w d4,d7 add.w d4,d7 movem.l 0(a3,d7),d5-d7 movem.l d5-d7,(a5) ; cmp.b 2(a4),d0 beq.s playend playsync2: btst #4,$d(a6) beq.s playsync2 bclr #4,$d(a6) bra playloop playend: bra sndinit2 see input loop, it's nearly the same SECTION DATA voldat: dc.l $08000000,$09000000,$0a000000 dc.l $08000000,$09000000,$0a000200 dc.l $08000000,$09000000,$0a000300 dc.l $08000200,$09000200,$0a000200 dc.l $08000500,$09000000,$0a000000 dc.l $08000500,$09000200,$0a000000 dc.l $08000600,$09000100,$0a000000 dc.l $08000600,$09000200,$0a000100 dc.l $08000700,$09000100,$0a000000 dc.l $08000700,$09000200,$0a000000 dc.l $08000700,$09000300,$0a000100 dc.l $08000800,$09000000,$0a000000 dc.l $08000800,$09000200,$0a000000 dc.l $08000800,$09000300,$0a000100 dc.l $08000800,$09000400,$0a000100 dc.l $08000900,$09000000,$0a000000 dc.l $08000900,$09000200,$0a000000 dc.l $08000900,$09000300,$0a000100 dc.l $08000900,$09000400,$0a000100 dc.l $08000900,$09000500,$0a000000 dc.l $08000900,$09000500,$0a000200 dc.l $08000900,$09000600,$0a000000 dc.l $08000900,$09000600,$0a000200 dc.l $08000a00,$09000200,$0a000000 dc.l $08000a00,$09000200,$0a000200 dc.l $08000a00,$09000400,$0a000100 dc.l $08000a00,$09000500,$0a000000 dc.l $08000a00,$09000500,$0a000200 dc.l $08000a00,$09000600,$0a000100 dc.l $08000a00,$09000600,$0a000300 dc.l $08000b00,$09000100,$0a000000 dc.l $08000b00,$09000200,$0a000100 dc.l $08000b00,$09000300,$0a000100 dc.l $08000b00,$09000400,$0a000100 dc.l $08000b00,$09000500,$0a000100 dc.l $08000b00,$09000600,$0a000000 dc.l $08000b00,$09000600,$0a000200 dc.l $08000b00,$09000700,$0a000000 dc.l $08000b00,$09000700,$0a000100 dc.l $08000b00,$09000700,$0a000300 dc.l $08000b00,$09000700,$0a000400 dc.l $08000b00,$09000800,$0a000100 dc.l $08000b00,$09000800,$0a000300 dc.l $08000b00,$09000800,$0a000400 dc.l $08000b00,$09000800,$0a000500 dc.l $08000b00,$09000800,$0a000500 dc.l $08000c00,$09000200,$0a000000 dc.l $08000c00,$09000200,$0a000200 dc.l $08000c00,$09000400,$0a000100 dc.l $08000c00,$09000500,$0a000000 dc.l $08000c00,$09000500,$0a000300 dc.l $08000c00,$09000600,$0a000000 dc.l $08000c00,$09000600,$0a000200 dc.l $08000c00,$09000700,$0a000000 dc.l $08000c00,$09000700,$0a000300 dc.l $08000c00,$09000700,$0a000400 dc.l $08000c00,$09000800,$0a000000 dc.l $08000c00,$09000800,$0a000300 dc.l $08000c00,$09000800,$0a000400 dc.l $08000c00,$09000800,$0a000500 dc.l $08000c00,$09000900,$0a000000 dc.l $08000c00,$09000900,$0a000300 dc.l $08000c00,$09000900,$0a000400 dc.l $08000c00,$09000900,$0a000500 siditab: dc.b 0,$ff,1,$ff,2,$ff,3,$ff,4,$ff,5,$ff,6,0,7,$3f dc.b 8,0,9,0,10,0,$ff,0 even smp_anf_: dc.l 1000000 smp_end_: dc.l 1000000 smp_frq_: dc.w 20000 smp_mod_: dc.w 0 smp_way_: dc.w 1 smp_out_: dc.b $39 even smp_len_: dc.l 5 oldsp: dc.l 1 jaja: dc.l 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,9,0