diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/1-sqlite-basic.csd | 41 | ||||
| -rw-r--r-- | examples/2-sqlite-krate.csd | 95 | ||||
| -rw-r--r-- | examples/3-postgresql-basic.csd | 100 | ||||
| -rw-r--r-- | examples/4-postgresql-analysis.csd | 104 | ||||
| -rw-r--r-- | examples/5-mysql-basic.csd | 110 | ||||
| -rw-r--r-- | examples/6-mysql-randomnotes.csd | 99 | ||||
| -rw-r--r-- | examples/7-violsqlite.csd | 172 | ||||
| -rw-r--r-- | examples/sounds/violin.wav | bin | 0 -> 586448 bytes | |||
| -rw-r--r-- | examples/toCheck/7-sqlite-pitchmatcher.csd | 140 | 
9 files changed, 861 insertions, 0 deletions
| diff --git a/examples/1-sqlite-basic.csd b/examples/1-sqlite-basic.csd new file mode 100644 index 0000000..8177d4a --- /dev/null +++ b/examples/1-sqlite-basic.csd @@ -0,0 +1,41 @@ +<CsoundSynthesizer> +<CsOptions> +-odac +</CsOptions> +<CsInstruments> +/* +    EXAMPLE 1 + +    print some data from a sqlite3 database at i-rate +     + +*/ + +sr = 44100 +kr = 4410 +nchnls = 2 +0dbfs = 1 +seed 0 + +; sqlite3 takes a file path, or :memory: for a temporary in-memory database +; gidb dbconnect "sqlite", "/tmp/example.db" +gidb dbconnect "sqlite", ":memory:" + +instr start_example + +    ; print a random value +    ires1 dbscalar gidb, "SELECT RANDOM()" +    print ires1 + +    ; print the second column (1) of the first row (0) +    ires2 dbscalar gidb, "SELECT 99, 98", 0, 1 +    print ires2 +endin + + +</CsInstruments> +<CsScore> +i "start_example" 0 1 + +</CsScore> +</CsoundSynthesizer>
\ No newline at end of file diff --git a/examples/2-sqlite-krate.csd b/examples/2-sqlite-krate.csd new file mode 100644 index 0000000..d6a370f --- /dev/null +++ b/examples/2-sqlite-krate.csd @@ -0,0 +1,95 @@ +<CsoundSynthesizer> +<CsOptions> +-odac +</CsOptions> +<CsInstruments> +/* +    EXAMPLE 2 + +    Use a metro to trigger the insertion of points from a line into a sqlite database, +    then read back the points in reverse order and play back with enveloping +     + +*/ + +sr = 44100 +kr = 4410 +nchnls = 2 +0dbfs = 1 +seed 0 + + +; sqlite3 takes a file path, or :memory: for a temporary in-memory database +;gidb dbconnect "sqlite", ":memory:" +gidb dbconnect "sqlite", "/tmp/example.db" + + +instr start_example + +    ; create the table with just one float column +    kdone1 dbexec_k gidb, "CREATE TABLE IF NOT EXISTS frequencies (freq float)", -1 + +    ; execute when create table statement has completed - clear out if the table does exist  +    kdone2 dbexec_k gidb, "DELETE FROM frequencies", kdone1 +     +    ; execute when delete has completed +    schedkwhen kdone2, 0, 0, "db_insert", 0, 5 +    schedkwhen kdone2, 0, 0, "db_select", 5, 10 + + +endin + + +; insert frequency values from line into database at k rate +instr db_insert + +    ; generate some data and print +    kfreq line 440, p3, 1000 +    ktrigger metro 5 +    printk 0.2, kfreq + +    ; insert snapshot with each metro (as long as the last query is still not pending) +    Squery sprintfk "INSERT INTO frequencies (freq) VALUES (%f)", kfreq +    kdone dbexec_k gidb, Squery, ktrigger +     +endin + + +; read frequency values from database at i rate: obtain the values in reverse order  +instr db_select + +    ; get all values in descending order into an array +    ires[][] dbarray gidb, "SELECT freq FROM frequencies ORDER BY freq desc" +    itimestep = 0.3 +    index = 0 +    itime = 0 +    ilast = 0 + +    ; loop through the values and play the frequency with some basic interpolation between last current values +    while (index < lenarray(ires)) do +        if (ilast != 0) then +            event_i "i", "playpitch", itime, itimestep, ilast, ires[index][0] +        endif +        ilast = ires[index][0] +        index += 1 +        itime += itimestep * 0.8 +    od +endin + + +; basic oscillator instrument with envelope +instr playpitch +    ipitch1 = p4 +    ipitch2 = p5 +    kamp linseg 0, p3*0.2, 1, p3*0.6, 1, p3*0.2, 0 +    kpitch line ipitch1, p3, ipitch2 +    aout oscil 0.8, kpitch +    outs aout*kamp, aout*kamp +endin + +</CsInstruments> +<CsScore> +i "start_example" 0 15 + +</CsScore> +</CsoundSynthesizer>
\ No newline at end of file diff --git a/examples/3-postgresql-basic.csd b/examples/3-postgresql-basic.csd new file mode 100644 index 0000000..053ee07 --- /dev/null +++ b/examples/3-postgresql-basic.csd @@ -0,0 +1,100 @@ +<CsoundSynthesizer> +<CsOptions> +-odac +</CsOptions> +<CsInstruments> +/* +    EXAMPLE 3 + +    Run some queries on a PostgreSQL database using just inbuilt functions and system tables +     + +*/ + +sr = 44100 +kr = 4410 +nchnls = 2 +0dbfs = 1 +seed 0 + + +; connect: type, hostname or IP, database name, username, password +gidb dbconnect "postgresql", "localhost", "databasename", "username", "password" + + +; print a random float from the database +instr execscalar +    ires dbscalar gidb, "SELECT RANDOM()" +    print ires +endin + + +; print the current_timestamp from the database +instr execscalarstr +    Sres dbscalar gidb, "SELECT current_timestamp || '\n'" +    prints Sres +endin + + +; print some float columns from the database activity statistics table +instr execarray +    ires[][] dbarray gidb, "SELECT datid, pid, usesysid FROM pg_stat_activity" +    printarray ires +endin + + +; print some string columns from the database activity table +instr execarraystr +    Sres[][] dbarray gidb, "SELECT datname, usename, state, query_start FROM pg_stat_activity" +    irow = 0 + +    ; loop through as printarray does not support multidimensional string arrays +    while (irow < lenarray(Sres)) do +        icol = 0 +        while (icol < 3) do +            Sitem sprintf "%d, %d : %s\n", irow, icol, Sres[irow][icol] +            prints Sitem +            icol += 1 +        od +        irow += 1 +    od +     +endin + + +; print the current_timestamp from the database server twice per second, and print when the query has been executed +instr execscalar_k +    ktrigger metro 2 +    kdone, Sres dbscalar_k gidb, "SELECT 'now = ' || current_timestamp || '\n'", ktrigger +    if (kdone == 1) then +        printks "%s", 0, Sres +    endif +endin + + +; print 2x2 random floats from the database every second +instr execarray_k +    ktrigger metro 1 +    kdone, kres[][] dbarray_k gidb, "SELECT RANDOM(), RANDOM() UNION SELECT RANDOM(), RANDOM()", ktrigger +    if (kdone == 1) then +        printk2 kres[0][0] +        printk2 kres[0][1] +        printk2 kres[1][0] +        printk2 kres[1][1] +    endif + +endin + + +</CsInstruments> +<CsScore> + +i "execscalar" 0 1 +i "execscalarstr" 2 1 +i "execarray" 4 1 +i "execarraystr" 6 1 +i "execscalar_k" 7 5 +i "execarray_k" 12 5 + +</CsScore> +</CsoundSynthesizer>
\ No newline at end of file diff --git a/examples/4-postgresql-analysis.csd b/examples/4-postgresql-analysis.csd new file mode 100644 index 0000000..38a82a6 --- /dev/null +++ b/examples/4-postgresql-analysis.csd @@ -0,0 +1,104 @@ +<CsoundSynthesizer> +<CsOptions> +-odac +</CsOptions> +<CsInstruments> +/* +	EXAMPLE 4 + +	Pitch track an oscillator, inserting the time, frequency and amplitude values in a PostgreSQL database  +	as fast as it will accept, at k-rate. +	Read back the values at i-rate in the db_play instrument and create events to mimic the original oscillator. +	 + +*/ + +sr = 44100 +kr = 4410 +nchnls = 2 +0dbfs = 1 +seed 0 + + +; connect: type, hostname or IP, database name, username, password +gidb dbconnect "postgresql", "localhost", "databasename", "username", "password" + + +; create table if it doesn't exist. truncate if it does +instr start_example +	kdone1 dbexec_k gidb, "CREATE TABLE IF NOT EXISTS analysis (time FLOAT, rms FLOAT, freq FLOAT)", -1 +	kdone2 dbexec_k gidb, "TRUNCATE TABLE analysis", kdone1 + +	; schedule next steps +	if (kdone2 == 1) then +		schedule "db_analyse", 0, 3 +		schedule "db_play", 3.5, 3.5 +		turnoff +	endif +endin + + +instr db_analyse +	 +	; the oscillator +	a1 oscil abs(oscil(1, 0.6)), linseg(440, p3*0.2, 800, p3*0.2, 220, p3*0.2, 220, p3*0.2, 350, p3*0.2, 440) + +	; pitch/rms and time tracking +	kcps, krms pitchamdf a1, 220, 800, 0, 0 +	ktime timeinsts  + +	; listen back to the pitch track output +	a1 oscil krms, kcps + +	; insert the time, rms and frequency values as fast as the database will accept +	kdone init 1 +	kdone dbexec_k gidb, sprintfk("INSERT INTO analysis (time, rms, freq) VALUES (%f, %f, %f)", ktime, krms, kcps), 1 +	 +	; declick end +	aout = a1 * linseg(1, p3*0.99, 1, p3*0.01, 0) +	outs aout, aout +endin + + +instr db_play + +	; get all of the values +	idata[][] dbarray gidb, "SELECT time, rms, freq FROM analysis" +	 +	; loop through  +	index = 0 +	while (index < lenarray(idata)) do +	 +		; set the duration to be the time to the next row multiplied by an overlap +		if (index == lenarray(idata) - 1) then +			iduration = 1 +		else	 +			iduration = (idata[index+1][0] - idata[index][0]) * 3.2 +		endif +	 +		; create the event accordingly +		event_i "i", "oscillator", idata[index][0]*2, iduration, idata[index][1], idata[index][2] +		index += 1 +	od +endin + + +instr oscillator + +	; basic oscillator +	iamp = p4 +	ifreq = p5 +	a1 oscil iamp * 0.5, ifreq +	 +	; envelope to try and take away the quantised type sound +	aout = a1 * linseg(0, p3*0.45, 1, p3*0.1, 1, p3*0.45, 0) +	outs aout, aout +endin + +</CsInstruments> +<CsScore> +i "start_example" 0 7 + + +</CsScore> +</CsoundSynthesizer>
\ No newline at end of file diff --git a/examples/5-mysql-basic.csd b/examples/5-mysql-basic.csd new file mode 100644 index 0000000..bf8e857 --- /dev/null +++ b/examples/5-mysql-basic.csd @@ -0,0 +1,110 @@ +<CsoundSynthesizer> +<CsOptions> +-odac +</CsOptions> +<CsInstruments> +/* +    EXAMPLE 3 + +    Run some queries on a MySQL database using just inbuilt functions and system tables +     + +*/ + +sr = 44100 +kr = 4410 +nchnls = 2 +0dbfs = 1 +seed 0 + + +; connect: type, hostname or IP, database name, username, password +gidb dbconnect "mysql", "hostname", "databasename", "user", "password" + + +; print a random float from the database +instr execscalar +    ires dbscalar gidb, "SELECT RAND()" +    print ires +endin + + +; print the current_timestamp from the database +instr execscalarstr +    Sres dbscalar gidb, "SELECT CONCAT(NOW(), '\n')" +    prints Sres +endin + + +; print some float columns from the database activity statistics table +instr execarray +    Sql = {{ +        SELECT INDEX_LENGTH, AVG_ROW_LENGTH, TABLE_ROWS  +        FROM INFORMATION_SCHEMA.TABLES  +        LIMIT 10 +    }} +    ires[][] dbarray gidb, Sql +    printarray ires +endin + + +; print some string columns from the database activity table +instr execarraystr +    Sql = {{ +        SELECT TABLE_NAME, TABLE_COMMENT, ROW_FORMAT +        FROM INFORMATION_SCHEMA.TABLES  +        LIMIT 10 +    }} +    Sres[][] dbarray gidb, Sql +    irow = 0 + +    ; loop through as printarray does not support multidimensional string arrays +    while (irow < lenarray(Sres)) do +        icol = 0 +        while (icol < 3) do +            Sitem sprintf "%d, %d : %s\n", irow, icol, Sres[irow][icol] +            prints Sitem +            icol += 1 +        od +        irow += 1 +    od +     +endin + + +; print the current_timestamp from the database server twice per second, and print when the query has been executed +instr execscalar_k +    ktrigger metro 2 +    kdone, Sres dbscalar_k gidb, "SELECT CONCAT('now = ', NOW(), '\n')", ktrigger +    if (kdone == 1) then +        printks "%s", 0, Sres +    endif +endin + + +; print 2x2 random floats from the database every second +instr execarray_k +    ktrigger metro 1 +    kdone, kres[][] dbarray_k gidb, "SELECT RAND(), RAND() UNION SELECT RAND(), RAND()", ktrigger +    if (kdone == 1) then +        printk2 kres[0][0] +        printk2 kres[0][1] +        printk2 kres[1][0] +        printk2 kres[1][1] +    endif + +endin + + +</CsInstruments> +<CsScore> + +i "execscalar" 0 1 +i "execscalarstr" 2 1 +i "execarray" 4 1 +i "execarraystr" 6 1 +i "execscalar_k" 7 5 +i "execarray_k" 12 5 + +</CsScore> +</CsoundSynthesizer>
\ No newline at end of file diff --git a/examples/6-mysql-randomnotes.csd b/examples/6-mysql-randomnotes.csd new file mode 100644 index 0000000..036b63a --- /dev/null +++ b/examples/6-mysql-randomnotes.csd @@ -0,0 +1,99 @@ +<CsoundSynthesizer> +<CsOptions> +-odac +</CsOptions> +<CsInstruments> +/* +    EXAMPLE 3 + +    Insert some frequencies and durations to a MySQL database +    then query/play random pairs +     + +*/ + +sr = 44100 +kr = 4410 +nchnls = 2 +0dbfs = 1 +seed 0 + + +; connect: type, hostname or IP, database name, username, password +gidb dbconnect "mysql", "localhost", "databasename", "username", "password" + + +; initialise the example +instr start_example + +    ; create tables if not existing/truncate if existing and fill with frequency and duration data +    dbexec gidb, "CREATE TABLE IF NOT EXISTS frequencies (freq FLOAT)" +    dbexec gidb, "TRUNCATE TABLE frequencies" +    dbexec gidb, "CREATE TABLE IF NOT EXISTS durations (dur FLOAT)" +    dbexec gidb, "TRUNCATE TABLE durations" +    dbexec gidb, "INSERT INTO frequencies (freq) VALUES (277.2), (349.272), (415.24559), (523.35359), (391.96079)" +    dbexec gidb, "INSERT INTO frequencies (freq) SELECT freq*2 FROM frequencies" +    dbexec gidb, "INSERT INTO durations (dur) VALUES (0.1), (0.2), (0.4), (0.8), (1), (1.2)" + +    ; run the sequencer instrument for 30 seconds +    event_i "i", "sequence", 0, 30 +endin + + +; random sequencer instrument +instr sequence + +    ; query to return random frequency/duration pair +    Sql = {{ +        SELECT f.freq, d.dur +        FROM frequencies f  +        JOIN (SELECT dur FROM durations ORDER BY RAND() LIMIT 1) d +        ORDER BY RAND()  +        LIMIT 1 +    }} + +    ; array needs to be initialised or schedkwhen complains +    kevent[][] init 1, 2     + +    ; query twice per second +    ktrig metro 3 +     +    ; query on metro returning the frequency/duration pair +    kdone, kevent[][] dbarray_k gidb, Sql, ktrig + +    ; schedule the note +    schedkwhen kdone, 0, 0, "osc", 0, kevent[0][1], kevent[0][0] + +endin + + +; play a note +instr osc + +    ; pick a random waveform +    ifn = int(random(1, 4)) + +    ; set frequency and envelope +    ifreq = p4 +    kamp line 0.5, p3, 0 + +    ; play it +    a1 oscil kamp, ifreq, ifn +    outs a1, a1 +endin + + + + +</CsInstruments> +<CsScore> +f1 0 16384 10 1 +f2 0 16384 10 1 0.5 0.3 0.25 0.2 0.167 0.14 0.125 .11 +f3 0 16384 10 1 0 0.3 0 0.2 0 0.14 0 .111 +f4 0 16384 10 1 1 1 1 0.7 0.5 0.3 0.1 + +; begin example +i "start_example" 0 1 + +</CsScore> +</CsoundSynthesizer>
\ No newline at end of file diff --git a/examples/7-violsqlite.csd b/examples/7-violsqlite.csd new file mode 100644 index 0000000..cabc753 --- /dev/null +++ b/examples/7-violsqlite.csd @@ -0,0 +1,172 @@ +<CsoundSynthesizer> +<CsOptions> +-odac +</CsOptions> +<CsInstruments> +/* +    EXAMPLE 7 + +    A rudimentary pitch tracking concatenative resynthesizer as such + +    This creates a sqlite database in memory, and then uses the opcode getpitches to scan through a  +    sound file in non-realtime, storing detected pitches and the relevant offset time of the pitch in  +    the database. The example file is a descending violin glissando. +     +    When done, the instrument "playmatches" is scheduled twice which plays an oscillator varying in pitch, +    which is pitch tracked and the nearest frequency is found in the database, prompting the "segment" +    instrument to be scheduled with the relevant offset. + + +	1. for 20s in which nearest matches are played only if the detected pitch has changed outside of a threshold  +	2. as above but with matches played continuously  + +    The result is that the violin segments picked should moreorless match what the oscillator is doing. + +*/ + +sr = 44100 +kr = 4410 +nchnls = 2 +0dbfs = 1 + + +; create an in-memory sqlite database and create a table +gidb  dbconnect "sqlite", ":memory:" +dbexec gidb, "CREATE TABLE pitches (time REAL, cps REAL)" + +; file of ascending piano pitches +gSfile = "sounds/violin.wav" +gifn ftgen 0, 0, 0, 1, gSfile, 0, 0, 0 + +; detect pitches and insert time/cps to database given a filename, in non-realtime +opcode getpitches, 0, S +    Sfile xin +    ktimek timeinstk +    ktime timeinsts +    klast init -1 +    kcount init 0 + +    ; run in the first single k-rate cycle +    if (ktimek == 0) then + +        ; get file length in k-cycles +        ilen filelen Sfile +        kcycles = ilen * kr +loop:         +        ; read file and track pitch +        ain diskin2 Sfile, 1 +	;ain butterbp ain, 500, 250 +        koct, kamp pitch ain, 0.01, 6, 12, 6, 12, 60 +	 +        ; only take action if pitch has changed +        kchanged changed2 koct +        if (kchanged == 1) then +		 +            ; only store if cps is reasonably different from the last value +            kcps = cpsoct(koct) + +            if (1==1) then + +                ; insert to database: the dbexec_kb opcode is k-rate but blocking/synchronous.  +                ; simpler to use for the non-realtime operation as regular _k opcodes are threaded/asynchronous +                ktime = kcount / kr +                Squery sprintfk "INSERT INTO pitches (time, cps) VALUES (%f, %f)", ktime, kcps +                dbexec_kb gidb, Squery +                klast = kcps +            endif +        endif +        loop_lt kcount, 1, kcycles, loop +         +    endif +endop + + + +; begin the example: find pitches and then schedule the next step +instr start_example +    getpitches gSfile +    schedkwhen 1, 0, 0, "playmatches", 0, 20, 0 +    schedkwhen 1, 0, 0, "playmatches", 20, 20, 1 +    turnoff + +endin + + + +; pitch follow a descending oscillator and attempt to find a similar cps in the database, then schedule segment accordingly +instr playmatches +    kdone init 0    ; for when the select query is done +    klast init 0    ; last pitch played, in order to avoid repeats + + +    ; oscillator +    k1 linseg 400, p3, 200 +    ktime linseg 0.001, p3, 2 +    k2 oscil k1, ktime +    ain oscil 1, abs(k2)+550, 1 + +    ; track it +    koct, kamp pitch ain, 0.01, 5, 10, 6, 12 +	 +    ; only take action when the tracked pitch has changed +    kchanged changed2 koct +    if (kchanged == 1) then + +        ; (very roughly) get a near frequency match from the database +        kcps = cpsoct(koct) +         +        ; fairly nasty looking query for obtaining the nearest value +        SquerySource = {{ +            SELECT time FROM ( +                SELECT time, cps FROM ( +                    SELECT time, cps FROM pitches WHERE cps >= %f ORDER BY cps ASC LIMIT 1 +                )  +                UNION SELECT time, cps FROM ( +                    SELECT time, cps FROM pitches WHERE cps < %f ORDER BY cps DESC LIMIT 1 +                ) +            ) x ORDER BY ABS(cps - %f) ASC LIMIT 1 +        }} + +        Squery sprintfk SquerySource, kcps, kcps, kcps +        kdone, kpos dbscalar_k gidb, Squery, kchanged + +        ;schedule the notes +        if (p4 == 1) then +            schedkwhen kdone, 0, 0, "segment", 0, 0.2, kpos         +        else +            if (kpos < klast*0.8 || kpos > klast*1.2) then +                schedkwhen kdone, 0, 0, "segment", 0, 0.2, kpos +                klast = kpos +            endif +        endif +    endif + +    +    ; uncomment to hear the oscillator as well as pitch matched output +    ;outs ain*0.01, ain*0.01 +endin + + + +; play part of the sound file given a skip time with a basic envelope +instr segment +    il = ftlen(gifn) +    isec = il/sr          +    ist = sr*p4 +    icps = 1/isec   +    aphs phasor icps       +    andx = aphs * il +    aout tablei andx+ist, gifn +    kamp linseg 0, p3*0.3, 1, p3*0.4, 1, p3*0.3, 0 +    outs aout*0.1*kamp, aout*0.1*kamp +endin + + +</CsInstruments> +<CsScore> +f1 0 16384 10 1 0 0.3 0 0.2 0 0.14 0 .111 ; square wave + +i"start_example" 0 1 + +</CsScore> +</CsoundSynthesizer>
\ No newline at end of file diff --git a/examples/sounds/violin.wav b/examples/sounds/violin.wavBinary files differ new file mode 100644 index 0000000..c490e1c --- /dev/null +++ b/examples/sounds/violin.wav diff --git a/examples/toCheck/7-sqlite-pitchmatcher.csd b/examples/toCheck/7-sqlite-pitchmatcher.csd new file mode 100644 index 0000000..1d45234 --- /dev/null +++ b/examples/toCheck/7-sqlite-pitchmatcher.csd @@ -0,0 +1,140 @@ +<CsoundSynthesizer> +<CsOptions> +-odac +</CsOptions> +<CsInstruments> +/* +    EXAMPLE 9 + +    A rudimentary pitch tracking concatenative resynthesizer + +    This creates a sqlite database in memory, and then uses the opcode getpitches to scan through a  +    sound file in non-realtime, storing detected pitches and the relevant offset time of the pitch in  +    the database. The example file is a series of ascending piano notes. +     +    When done, the instrument "playmatches" is scheduled. This plays a descending oscillator +    which is pitch tracked and then a similar pitch is found from the database, prompting the "segment"  +    instrument to be scheduled with the relevant offset. +    The result is that the piano notes/sound file segments picked should moreorless match what the  +    oscillator is doing. + +*/ + +sr = 44100 +kr = 4410 +nchnls = 2 +0dbfs = 1 + + +; create an in-memory sqlite database and create a table +gidb  dbconnect "sqlite", ":memory:" +dbexec gidb, "CREATE TABLE pitches (time REAL, cps REAL)" + +; file of ascending piano pitches +gSfile = "sounds/piano.wav" + + +; detect pitches and insert time/cps to database given a filename, in non-realtime +opcode getpitches, 0, S +    Sfile xin +    ktimek timeinstk +    ktime timeinsts +    klast init -1 +    kcount init 0 + +    ; run in the first single k-rate cycle +    if (ktimek == 0) then + +        ; get file length in k-cycles +        ilen filelen Sfile +        kcycles = ilen * kr +loop:         +        ; read file and track pitch +        ain diskin2 Sfile, 1 +        koct, kamp pitch ain, 0.01, 7, 11, 6, 12, 10, 8 + +        ; only take action if pitch has changed +        kchanged changed2 koct +        if (kchanged == 1) then + +            ; only store if cps is reasonably different from the last value +            kcps = cpsoct(koct) +            if (kcps > klast*1.1 || kcps < klast*0.9) then + +                ; insert to database: the dbexec_kb opcode is k-rate but blocking/synchronous.  +                ; simpler to use for the non-realtime operation as regular _k opcodes are threaded/asynchronous +                ktime = kcount / kr +                Squery sprintfk "INSERT INTO pitches (time, cps) VALUES (%f, %f)", ktime, kcps +                dbexec_kb gidb, Squery +                klast = kcps +            endif +        endif +        loop_lt kcount, 1, kcycles, loop +         +    endif +endop + + + +; begin the example: find pitches and then schedule the next step +instr start_example +    getpitches gSfile +    schedkwhen 1, 0, 0, "playmatches", 0, 20 +    turnoff + +endin + + + +; pitch follow a descending oscillator and attempt to find a similar cps in the database, then schedule segment accordingly +instr playmatches +    kdone init 0    ; for when the select query is done +    klast init 0    ; last pitch played, in order to avoid repeats + +    ; descending oscillator +    k1 linseg 2000, p3, 200 +    ain oscil 1, k1, 1 + +    ; track it +    koct, kamp pitch ain, 0.01, 7, 11, 6, 12, 10, 8 + +    ; only take action when the tracked pitch has changed +    kchanged changed2 koct +    if (kchanged == 1) then + +        ; (very roughly) get a near frequency match from the database +        kcps = cpsoct(koct) +        Squery sprintfk "SELECT time FROM pitches WHERE cps >= %f LIMIT 1", kcps +        kdone, kpos dbscalar_k gidb, Squery, kchanged + +        ; don't repeat notes (try the schedkwhen outside of the if block for continuous play) +        if (kpos != klast) then +            schedkwhen kdone, 0, 0, "segment", 0, 0.2, kpos +            klast = kpos +        endif +    endif +     +    ; uncomment to hear the oscillator as well as pitch matched output +    ;outs ain*0.01, ain*0.01 +endin + + + +; play part of the sound file given a skip time with a basic fade in/out +instr segment +    iskip = p4 +    kamp linseg 0, p3*0.1, 1, p3*0.8, 1, p3*0.1, 0 +    a1 diskin2 gSfile, 1, iskip +    aout = a1*kamp * 0.1 +    outs aout, aout +endin + + +</CsInstruments> +<CsScore> +f1 0 16384 10 1 0 0.3 0 0.2 0 0.14 0 .111 ; square wave + +i"start_example" 0 1 + +</CsScore> +</CsoundSynthesizer>
\ No newline at end of file |