Last active
September 12, 2018 11:27
-
-
Save ElectricImpSampleCode/16523b6f33b3f70b48a7cc3672e0b15f to your computer and use it in GitHub Desktop.
imp004m Audio Kit Sample Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Set up the variables | |
local receiveBuffers = []; | |
local size = 0; | |
// Define the handler for storing audio from the device | |
device.on("store.audio.data", function(buffer) { | |
// Break the incoming data down into 1024-byte chunks | |
while (buffer.tell() < buffer.len()) { | |
local store = blob(); | |
local bytesleft = buffer.len() - buffer.tell(); | |
local toread = bytesleft > 1024 ? 1024 : bytesleft; | |
store.writeblob(buffer.readblob(toread)); | |
receiveBuffers.append(store); | |
} | |
size += buffer.len(); | |
server.log("Total audio data size " + size + " bytes"); | |
}); | |
// Define the handler for storing audio from the device | |
device.on("start.audio.stream", function(bufferCount) { | |
local sendBuffers = []; | |
local numberBuffersToSend = bufferCount < receiveBuffers.len() ? bufferCount : receiveBuffers.len(); | |
server.log("Sending " + numberBuffersToSend + " buffers"); | |
// Get the first buffers as the initial batch | |
for (local i = 0 ; i < numberBuffersToSend ; i++) { | |
sendBuffers.append(receiveBuffers.remove(0)); | |
} | |
// Bundle the data and send it to the device | |
local playbackData = {}; | |
playbackData.samples <- size; | |
playbackData.buffers <- sendBuffers; | |
device.send("start.audio.stream", playbackData); | |
}); | |
// Define the handler for sending audio to the device | |
device.on("get.audio.data", function(dummy) { | |
if (receiveBuffers.len() > 0) { | |
device.send("send.audio.data", receiveBuffers.remove(0)); | |
} | |
}); | |
// Define the handler for resetting the audio storage | |
device.on("reset.all", function(dummy) { | |
receiveBuffers = []; | |
size = 0; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// LIBRARY IMPORTS | |
#require "Button.class.nut:1.2.0" | |
// GLOBAL VARIABLES | |
local recordingProcessor = A_LAW_COMPRESS; | |
local playbackProcessor = A_LAW_DECOMPRESS | AUDIO; | |
local dfsdmFilterOrder = 4; | |
local dfsdmDecRate = 64; | |
local dfsdmIntRate = 1; | |
local sampleRate = 15957; | |
local samplesPerBuffer = 1000; | |
local buffersReceived = 0; | |
local triggered = false; | |
local playing = false; | |
local useBothFFDACpins = true; | |
local outputBuffers = null; | |
local playbackSamples = 0; | |
local samplesPlayed = 0; | |
local samplesToSend = blob(); | |
local button = null; | |
// FUNCTIONS | |
function samplesReadyCallback(buffer, length) { | |
// Called by DFSDM when a buffer has been filled | |
// Check for a buffer over-run and log if it has occurred | |
if (buffer == null && length == 0) server.log("Sampling over-run occurred"); | |
// Do we have valid data? If so, send it to the agent | |
if (length > 0 && triggered) samplesToSend.writeblob(buffer); | |
if (samplesToSend.len() >= 8192 || (!triggered && samplesToSend.len() > 0)) { | |
if (!triggered) { | |
hardware.dfsdm.stop(); | |
hardware.pinB.configure(DIGITAL_OUT, 1); | |
} | |
agent.send("store.audio.data", samplesToSend); | |
samplesToSend = blob(); | |
if (!triggered) agent.send("start.audio.stream", 8); | |
} | |
} | |
function bufferEmptyCallback(buffer) { | |
if (buffer == null && (samplesPlayed < playbackSamples)) { | |
server.log("Playback under-run occurred") | |
agent.send("get.audio.data", true); | |
} else if (buffer != null) { | |
samplesPlayed += buffer.len(); | |
} | |
// Do we have audio data to play? | |
if (samplesPlayed < playbackSamples) { | |
if (outputBuffers.len() > 0) hardware.fixedfrequencydac.addbuffer(outputBuffers.remove(0)); | |
agent.send("get.audio.data", true); | |
} else { | |
server.log("Done"); | |
hardware.fixedfrequencydac.stop(); | |
hardware.pinB.configure(DIGITAL_OUT, 1); | |
playing = false; | |
reset(); | |
} | |
} | |
function setupFFDAC(buffers) { | |
// Configure the imp044m Audio Kit’s special FFDAC | |
hardware.fixedfrequencydac.configure(hardware.pwmpairKD, | |
sampleRate, | |
buffers, | |
bufferEmptyCallback, | |
playbackProcessor); | |
// If we don't want to use both imp004m FFDAC output pins, | |
// reconfigure the second pin, Pin D | |
if (!useBothFFDACpins) hardware.pinD.configure(DIGITAL_IN); | |
} | |
function setupDFSDM() { | |
hardware.dfsdm.reset(); | |
// Set up 8 blobs as input buffers | |
local inputBufferSize = samplesPerBuffer * 2; | |
local buffers = []; | |
for (local i = 0 ; i < 8 ; i++) { | |
buffers.append(blob(inputBufferSize)); | |
} | |
// Calculate the offset parameter: no offset for any | |
// recording mode other than NORMALISE | |
local offset = (recordingProcessor & NORMALISE) ? 8388608 : 0 | |
// Configure the imp044m Audio Kit’s DFSDM: | |
// Filter order 4; decimation rate 64; integration rate 1 | |
// Offset as above; right shift 0; sample on rising clock edge | |
hardware.dfsdm.configure(dfsdmFilterOrder, | |
dfsdmDecRate - 1, | |
dfsdmIntRate - 1, | |
offset, | |
0, | |
"RISING-EDGE", | |
buffers, | |
samplesReadyCallback, | |
recordingProcessor); | |
} | |
function reset() { | |
agent.send("reset.all", true); | |
outputBuffers = []; | |
setupDFSDM(); | |
playing = false; | |
triggered = false; | |
playbackSamples = 0; | |
samplesPlayed = 0; | |
samplesToSend = blob(); | |
} | |
function buttonReleased() { | |
if (!triggered) { | |
triggered = true; | |
// Clear playback buffers | |
outputBuffers = []; | |
// Turn the red light on | |
hardware.pinA.configure(DIGITAL_OUT, 0); | |
// Start recording | |
hardware.dfsdm.start(); | |
// Turn of recording after 4 seconds | |
imp.wakeup(3, function() { | |
triggered = false; | |
hardware.pinA.configure(DIGITAL_OUT, 1); | |
hardware.dfsdm.stop(); | |
}); | |
} | |
} | |
// RUNTIME start | |
// Power up the the MIC | |
hardware.pinQ.configure(DIGITAL_OUT, 1); | |
// Set up the PWM-generated MIC clock signal. This is the output | |
// clock rate * DFSDM decimation rate * DFSDM integration rate, | |
// NOTE 'sampleRate' is also the FFDAC's input rate | |
// The duty cycle is 50 per cent | |
local inputFrequency = sampleRate * dfsdmDecRate * dfsdmIntRate; | |
hardware.pinP.configure(PWM_OUT, | |
1.0 / inputFrequency, | |
0.5); | |
// Configure the DFSDM (input) | |
imp.setsendbuffersize(30720); | |
reset(); | |
// Configure the Audio Kit’s button as a recording trigger | |
hardware.pinW.configure(DIGITAL_IN); | |
button = Button(hardware.pinW, | |
DIGITAL_IN_PULLDOWN, | |
Button.NORMALLY_LOW, | |
null, | |
buttonReleased); | |
// Define the handler for receiving buffers from the agent | |
agent.on("start.audio.stream", function(data) { | |
server.log("Received the start of the audio stream with " + data.buffers.len() + " buffers (" + data.samples + " samples)"); | |
playbackSamples = data.samples; | |
if (!playing) { | |
// Turn green light on | |
hardware.pinB.configure(DIGITAL_OUT, 0); | |
// Use the first half of the supplied buffers to set up the FFDAC | |
local setupBuffers = []; | |
while (data.buffers.len()) setupBuffers.append(data.buffers.remove(0)); | |
setupFFDAC(setupBuffers); | |
// Start playback | |
hardware.fixedfrequencydac.start(); | |
playing = true; | |
} | |
}); | |
// Define the handler for receiving buffers from the agent | |
agent.on("send.audio.data", function (buffer) { | |
outputBuffers.append(buffer); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment