Last active
March 22, 2023 11:14
-
-
Save hatchjaw/689a3833af2e79f779bd17deb0805e72 to your computer and use it in GitHub Desktop.
Teensy Audio + QNEthernet multicast example
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
#include <Audio.h> | |
#include "MulticastNode.h" | |
AudioControlSGTL5000 audioShield; | |
AudioOutputI2S out; | |
MulticastNode node{true, false}; // flags to receive and send respectively. | |
AudioConnection patchCord1(node, 0, out, 0); | |
AudioConnection patchCord2(node, 1, out, 1); | |
AudioConnection patchCord3(node, 0, node, 0); | |
AudioConnection patchCord4(node, 1, node, 1); | |
void setup() { | |
while (!Serial); | |
node.begin(); | |
AudioMemory(16); | |
audioShield.enable(); | |
} | |
void loop() { | |
Serial.println("In loop()"); // Eventually stops being called... | |
delay(1000); | |
} |
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
#include "MulticastNode.h" | |
MulticastNode::MulticastNode(bool receive, bool send) : AudioStream(kNumChannels, new audio_block_t *[kNumChannels]), | |
rx{receive}, tx{send} { | |
} | |
void MulticastNode::begin() { | |
Ethernet.onLinkState([this](bool state) { | |
Serial.printf("[Ethernet] Link %s\n", state ? "ON" : "OFF"); | |
if (state) { | |
Serial.print("IP is "); | |
Serial.println(Ethernet.localIP()); | |
ready = udp.beginMulticast(multicastIP, localPort); | |
while (!ready) { | |
Serial.println("Failed to set up network connection."); | |
yield(); | |
} | |
Serial.println("Network connection established."); | |
} | |
}); | |
Ethernet.begin(localIP, netmask, gatewayIP); | |
} | |
void MulticastNode::update(void) { | |
if (rx) receive(); | |
audioOut(); | |
if (tx) send(); | |
} | |
void MulticastNode::receive() { | |
if (!ready) return; | |
int size; | |
while ((size = udp.parsePacket()) > 0) { | |
udp.read(buffer, size); | |
++received; | |
Serial.printf("Packet received (#%d), From ", received); | |
Serial.print(udp.remoteIP()); | |
Serial.printf(":%d, Length %d, Data: ", udp.remotePort(), size); | |
// Serial.write(buffer, size); | |
Serial.println(); | |
} | |
} | |
void MulticastNode::audioOut() { | |
audio_block_t *outBlock[kNumChannels]; | |
audio_block_t *inBlock[kNumChannels]; | |
auto channelFrameSize{AUDIO_BLOCK_SAMPLES * sizeof(int16_t)}; | |
for (int ch = 0; ch < kNumChannels; ++ch) { | |
inBlock[ch] = receiveReadOnly(ch); | |
outBlock[ch] = allocate(); | |
if (outBlock[ch] && inBlock[ch]) { | |
memcpy(outBlock[ch]->data, inBlock[ch], channelFrameSize); | |
memcpy(buffer + ch * channelFrameSize, inBlock[ch], channelFrameSize); | |
transmit(outBlock[ch], ch); | |
release(outBlock[ch]); | |
release(inBlock[ch]); | |
} | |
} | |
} | |
void MulticastNode::send() { | |
if (!ready) return; | |
auto size{kNumChannels * AUDIO_BLOCK_SAMPLES * sizeof(int16_t)}; | |
Serial.print("Sending packet, to: "); | |
Serial.print(multicastIP); | |
Serial.printf(":%d, Length: %d, Data:", remotePort, size); | |
// Serial.write(buffer, size); | |
Serial.println(); | |
auto err{udp.send(multicastIP, remotePort, buffer, size)}; | |
Serial.println(err); | |
if (err == ERR_OK) { | |
++sent; | |
Serial.println("Packet sent successfully."); | |
} | |
} |
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
#ifndef QNETHERNET_MINIMAL_MULTICASTNODE_H | |
#define QNETHERNET_MINIMAL_MULTICASTNODE_H | |
#include <Audio.h> | |
#include <QNEthernet.h> | |
using namespace qindesign::network; | |
class MulticastNode : public AudioStream { | |
public: | |
MulticastNode(bool receive, bool send); | |
void begin(); | |
private: | |
static constexpr int kNumChannels{2}; | |
void update(void) override; | |
void receive(); | |
void audioOut(); | |
void send(); | |
EthernetUDP udp{64}; | |
uint8_t buffer[EthernetClass::mtu() - 20 - 8]; | |
bool ready{false}; | |
const IPAddress multicastIP{226, 6, 38, 226}, | |
gatewayIP{192, 168, 10, 1}, localIP{192, 168, 10, 66}, netmask{255, 255, 255, 0}; | |
const uint16_t localPort{41814}, remotePort{41814}; | |
int received{0}, sent{0}; | |
bool rx, tx; | |
}; | |
#endif //QNETHERNET_MINIMAL_MULTICASTNODE_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
receive()
works for up to several thousand incoming 32-sample packets, but Teensy always locks up.send()
doesn't work at all.Specifying different packet-queue lengths doesn't appear to help, nor does switching to a
while
condition inMulticastNode::receive
Tested with QNEthernet 0.18.0 and 0.19.0.