import numpy as np
import matplotlib.pyplot as plt

%load_ext csoundmagics

"""
Explanation: Using ICsound
csoundmagics includes an ICsound class which is adapted from Andrés Cabrera's icsound module. ICsound is bound to the %%csound and %csound magics command.
This notebook is an adaptation of Andrés' icsound test notebook.
Starting the Csound engine
To use ICsound create an ICsound instance:
End of explanation
"""


cs = ICsound(port=12894)

"""
Explanation: Creating an ICsound object automatically starts the engine:
End of explanation
"""


help(cs.startEngine)

"""
Explanation: You can set the properties of the Csound engine with parameters to the startEngine() function.
End of explanation
"""


cs.startEngine()

"""
Explanation: The engine runs in a separate thread, so it doesn't block execution of python.
End of explanation
"""


%%csound 1
gkinstr init 1

%%csound
print i(gkinstr)

"""
Explanation: Use the %%csound magic command to directly type csound language code in the cell and send it to the engine. The number after the magic command is optional; it references the slot where the engine is running. If omitted, slot#1 is assumed.
End of explanation
"""


cs.printLog()

"""
Explanation: So where did it print?
End of explanation
"""


cs.fillTable(1, np.array([8, 7, 9, 1, 1, 1]))
cs.fillTable(2, [4, 5, 7, 0, 8, 7, 9, 6])

"""
Explanation: By default, messages from Csound are not shown, but they are stored in an internal buffer. You can view them with the printLog() function. If the log is getting too long and confusing, use the clearLog() function.
Function tables
You can create csound f-tables directly from python lists or numpy arrays:
End of explanation
"""


cs.plotTable(1)
cs.plotTable(2, reuse=True)
plt.grid()

"""
Explanation: Tables can be plotted in the usual matplotlib way, but ICsound provides a plotTable function which styles the graphs.
End of explanation
"""


cs.table(2)

cs.makeTable(2, 1024, 10, 1)
cs.makeTable(3, 1024, -10, 0.5, 1)
cs.plotTable(2)
cs.plotTable(3, reuse=True)
#ylim((-1.1,1.1))

cs.table(2)[100: 105]

"""
Explanation: You can get the function table values from the csound instance:
End of explanation
"""


%%csound 1
giHalfSine ftgen 0, 0, 1024, 9, .5, 1, 0

cs.plotTable('giHalfSine')

"""
Explanation: Tables can also be passed by their variable name in Csound:
End of explanation
"""


randsig = np.random.random((320, 720))
i = 0
for i, row in enumerate(randsig):
    cs.fillTable(50 + i, row)
    print(i, '..', end=' ')

cs.plotTable(104)

"""
Explanation: The following will create 320 tables with 720 points each:
End of explanation
"""


%%csound 1
instr 1
asig asds

%%csound 1
instr 1
asig oscil 0.5, 440
outs asig, asig

%%csound 1
instr 1
asig oscil 0.5, 440
outs asig, asig
endin

"""
Explanation: Sending instruments
You can send instruments to a running csound engine with the %%csound magic. Any syntax errors will be displayed inline.
End of explanation
"""


cs.setChannel("val", 20)

"""
Explanation: Channels
Csound channels can be used to send values to Csound. They can affect running instances of instruments by using the invalue/chnget opcodes:
End of explanation
"""


cs.channel("val")

"""
Explanation: You can also read the channels from Csound. These channels can be set from ICsound or within instruments with the outvalue/chnset opcodes:
End of explanation
"""


cs.startRecord("out.wav")

cs.sendScore("i 1 0 1")
import time
time.sleep(1)

cs.stopRecord()

!aplay out.wav

"""
Explanation: Recording the output
You can record the realtime output from csound:
End of explanation
"""


cs_client = ICsound()
cs_client.startClient()

cs.clearLog()

"""
Explanation: Remote engines
You can also interact with engines through UDP. Note that not all operations are available, notably reading f-tables, but you can send instruments and note events to the remote engine.
End of explanation
"""


cs_client.sendScore("i 1 0 1")
cs_client.sendCode("print i(gkinstr)")

"""
Explanation: Now send notes and instruments from the client:
End of explanation
"""


cs.printLog()

"""
Explanation: And show the log in the server:
End of explanation
"""


cs.stopEngine()

cs

"""
Explanation: Stopping the engine
End of explanation
"""


%csound -2
del cs_client

"""
Explanation: If we don't need cs_client anymore, we can delete its slot with the %csound line magic (note the single % sign and the negative slot#). The python instance cs_client can then be deleted:
End of explanation
"""


prefix = 'http://service.iris.edu/irisws/timeseries/1/query?'
SCNL_parameters = 'net=IU&sta=ANMO&loc=00&cha=BHZ&'
times = 'starttime=2005-01-01T00:00:00&endtime=2005-01-02T00:00:00&'
output = 'output=ascii'
import urllib
f = urllib.request.urlopen(prefix + SCNL_parameters + times + output)
timeseries = f.read()

import ctcsound
data = ctcsound.pstring(timeseries).split('\n')
dates = []
values = []

for line in data[1:-1]:
    date, val = line.split()
    dates.append(date)
    values.append(float(val))

plt.plot(values)

cs.startEngine()
cs.fillTable(1, values)

"""
Explanation: Audification
Reading Earthquake data through a web API (might take a few minutes):
End of explanation
"""


%%csound 1
instr 1
idur = p3
itable = p4
asig poscil 1/8000, 1/p3, p4
outs asig, asig
endin

"""
Explanation: Instrument to play back the earthquake data stored in a table:
End of explanation
"""


cs.sendScore('i 1 0 3 1')

"""
Explanation: Listen:
End of explanation
"""


cs.sendScore('i 1 0 7 1')

"""
Explanation: Slower:
End of explanation
"""


cs.sendScore('i 1 0 1 1')

"""
Explanation: Quicker:
End of explanation
"""


ics = ICsound(bufferSize=64)

ics.listInterfaces()

%%csound 2

instr 1
asig oscil 0.5, 440
outs asig, asig
endin

ics.sendScore("i 1 0 0.5")

%csound -2

del ics

cs.stopEngine()

"""
Explanation: Other tests
Another engine:
End of explanation
"""


