' Multipliers should be a multiple of the same thing ' in the vast majority of cases. Basis frequencies: DATA 21,21,21,21 ' Changing twenty-one into 24.5 makes four into a Jee, ' which is a dumb name for a letter. ' This is _like_ my opening chord in more traditional notation: ' PLAY "T200O0G>D>GA" ' That can be commented *in* if you want to compare, ' because it will not compile with freebasic. ' Those Jeez are *two* octaves apart. ' Specifies order of part separation -- left, right... ' S A T B SA TB SB TA ST BA Q DATA 4,4,4,4 DATA 3,3,3,3 DATA 2,2,2,2 DATA 1,1,1,1 DATA 4,3,4,3 DATA 2,1,2,1 DATA 4,1,4,1 DATA 2,3,2,3 DATA 4,2,4,2 DATA 1,3,1,3 DATA 1,2,3,4 ' For posterity, the harmony for my initial release went: ' 18,24,30,27,30,27,24 ' That makes a very atypical and beat-driven harmony with this ' instrument, and it stands out from melody in vocals. ' Bayse, Counterpoint, Melody, Harmony, (Beats*BeatsPerSecond). 100 DATA 4,6,16,24,3, 6,8,18,27,2, 8,5,14,23,3, 6,6,15,24,4 DATA 8,8,16,20,3, 6,5,12,23,2, 4,6,16,24,4, 0,0,0,0,6 OPTION BASE 1 DIM TwoPi, pi, FlipStart, Temp, beatspersecond AS DOUBLE DIM angle(4), velocity(4), Acceleration(4), Phase(4) AS DOUBLE DIM note(4), lastnote(4), length AS SINGLE DIM harmonics(4) AS SINGLE DIM samples, t, samplerate AS LONG DIM k, g, h, amp, basis AS INTEGER DIM part(11, 4), Sign(4) AS INTEGER DIM test AS STRING PRINT test = "0" ' Setting that to one is for a quick and dirty, ' monochromatic (one part at a time) synthesizer. beatspersecond = 27 / 3.84 ' After I trimmed and time-corrected the recordings of the four ' parts, I adjusted the synthesizer for them. pi = 3.141592653589793# TwoPi = pi * 2 samplerate = 8000 lastnote(1) = 0 lastnote(2) = 0 IF test <> "1" THEN OPEN "\sox\wish.bat" FOR OUTPUT AS #1 OPEN "\sox\wishr.raw" FOR OUTPUT AS #2 OPEN "\sox\wishf.raw" FOR OUTPUT AS #3 OPEN "\sox\wish.raw" FOR OUTPUT AS #4 END IF FOR k = 1 TO 4 READ harmonics(k) lastnote(k) = 0 NEXT k FOR h = 1 TO 11 READ part(h, 1), part(h, 2), part(h, 3), part(h, 4) NEXT h FOR h = 1 TO 11 FOR g = 1 TO 8 READ note(1), note(2), note(3), note(4), length ' SOUND note(4) * 23, length ' That can be commented in for a quick and dirty synthesizer, ' except in FreeBasic. ' FirstBasic does not support zero as a rest (see "wait" and "if"). IF test = "0" THEN IF note(1) = 0 AND lastnote(1) = 0 THEN samples = samplerate * length / beatspersecond GOSUB 300 GOTO 75 END IF IF note(1) = 0 AND lastnote(1) <> 0 THEN GOSUB 250 FOR k = 1 TO 4 lastnote(k) = note(k) NEXT k samples = samplerate * length / beatspersecond GOSUB 300 GOTO 75 END IF IF lastnote(1) = 0 AND note(1) <> 0 THEN FOR k = 1 TO 4 lastnote(k) = note(k) NEXT k samples = samplerate * length / beatspersecond GOSUB 300 GOTO 75 END IF IF note(1) <> 0 AND lastnote(1) <> 0 THEN samples = samplerate * length / beatspersecond / 300 GOSUB 300 samples = samplerate * length / beatspersecond FOR k = 1 TO 4 lastnote(k) = note(k) NEXT k GOSUB 300 GOTO 75 END IF END IF 75 NEXT g RESTORE 100 NEXT h IF test = "0" THEN samples = samplerate * 3.84 GOSUB 300 ' Leaving space for reverb decay mixing with dry vocals. PRINT #1, "sox -c 2 -r"; samplerate; " -sw wishf.raw wishf.wav stat" PRINT #1, "pause" PRINT #1, "sox -c 2 -r"; samplerate; " -sw wishr.raw wishr.wav stat" PRINT #1, "pause" PRINT #1, "sox -c 2 -r"; samplerate; " -sw wish.raw wish.wav stat" CLOSE #1, #2, #3, #4 END IF END 250 FOR k = 1 TO 4 Sign(k) = SGN(Phase(k)) angle(k) = angle(k) + velocity(k) Temp = SIN(angle(k)) IF SGN(Temp) <> Sign(k) THEN Phase(k) = 0 angle(k) = angle(k) - velocity(k) ELSE Phase(k) = Temp END IF NEXT k GOSUB 400 FOR k = 1 TO 4 IF Phase(k) <> 0 GOTO 250 NEXT k FlipStart = FlipStart + pi FOR k = 1 TO 4 angle(k) = FlipStart NEXT k RETURN 300 ' Calculate constants of change for write loop. FOR k = 1 TO 4 velocity(k) = TwoPi * lastnote(part(h, k)) * harmonics(k) / samplerate Acceleration(k) = (TwoPi * note(part(h, k)) * harmonics(k) / samplerate - velocity(k)) / samples NEXT k ' Main write loop. Static Phases problem solved at 250. FOR t = 1 TO samples FOR k = 1 TO 4 Phase(k) = SIN(angle(k)) NEXT k GOSUB 400 FOR k = 1 TO 4 angle(k) = angle(k) + velocity(k) velocity(k) = velocity(k) + Acceleration(k) NEXT k NEXT t RETURN 400 ' Write a sample in three files. amp = CINT(Phase(1) / 1.001 * 32767 - 1) PRINT #2, CHR$(amp AND 255); PRINT #2, CHR$((amp AND 65280) / 256); amp = CINT(Phase(2) * .9 * 32767 - 1) PRINT #2, CHR$(amp AND 255); PRINT #2, CHR$((amp AND 65280) / 256); amp = CINT(Phase(3) * .8 * 32767 - 1) PRINT #3, CHR$(amp AND 255); PRINT #3, CHR$((amp AND 65280) / 256); amp = CINT(Phase(4) * .75 * 32767 - 1) PRINT #3, CHR$(amp AND 255); PRINT #3, CHR$((amp AND 65280) / 256); amp = CINT((Phase(1) * .9033989 + Phase(3) * .8928) / 2 * 32767 - 1) PRINT #4, CHR$(amp AND 255); PRINT #4, CHR$((amp AND 65280) / 256); amp = CINT((Phase(2) * 1.0044 + Phase(4) * .837) / 2 * 32767 - 1) PRINT #4, CHR$(amp AND 255); PRINT #4, CHR$((amp AND 65280) / 256); RETURN