Skip to content

Instantly share code, notes, and snippets.

@ElectricImpSampleCode
Last active September 12, 2018 11:27
Show Gist options
  • Save ElectricImpSampleCode/16523b6f33b3f70b48a7cc3672e0b15f to your computer and use it in GitHub Desktop.
Save ElectricImpSampleCode/16523b6f33b3f70b48a7cc3672e0b15f to your computer and use it in GitHub Desktop.
imp004m Audio Kit Sample Code
// 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;
});
// 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