diff core/NetworkSend.cpp @ 111:9928b6366227 scope-refactoring

Refactored the Scope class into NetworkSend and Scope classes. No need for a global pointer anymore!
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 19 Aug 2015 22:40:05 +0100
parents
children 3168919fdb07
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/NetworkSend.cpp	Wed Aug 19 22:40:05 2015 +0100
@@ -0,0 +1,144 @@
+//scope.cpp
+#include <Scope.h>
+
+#define BUILD_FOR_UDPRECEIVE_PLUGIN
+#define NETWORK_AUDIO_BUFFER_SIZE 302
+
+//initialize the static members of NetworkSend
+bool NetworkSend::staticConstructed=false;
+std::vector<NetworkSend*> NetworkSend::objAddrs(0);
+AuxiliaryTask NetworkSend::transmitAudioTask=NULL;
+
+void transmitAudio(){
+	NetworkSend::sendAllData();
+}
+
+void NetworkSend::sendAllData(){
+	for(unsigned int n=0; n<NetworkSend::objAddrs.size(); n++){
+		NetworkSend::objAddrs[n]->sendData();
+	}
+}
+
+void NetworkSend::staticConstructor(){
+	if(staticConstructed==true)
+		return;
+	staticConstructed=true;
+	transmitAudioTask = BeagleRT_createAuxiliaryTask(transmitAudio, 95, "transmitAudioTask"); //TODO: allow variable priority
+};
+
+NetworkSend::NetworkSend()
+{
+	sampleCount = 0;
+	channel.doneOnTime=true;
+	channel.index=channel.headerLength; //leave space for the heading message (channel, timestamp)
+	channel.timestamp=0;
+	channel.activeBuffer=0;
+	channel.readyToBeSent=false;
+}
+NetworkSend::~NetworkSend(){
+	for(unsigned int n=0; n<objAddrs.size(); n++){ //keep track of deleted instances;
+		if(objAddrs[n]==this){
+			objAddrs.erase(objAddrs.begin()+n);
+			break;
+		}
+	}
+}
+
+void NetworkSend::setup(float aSampleRate){
+	setup(aSampleRate, 0, 9999, "192.168.7.1");//channelNumber=0
+}
+
+void NetworkSend::setup(float aSampleRate, int aChannelNumber, int aPort, const char *aServer){
+	staticConstructor(); //FIXME: ideally this should be in the constructor, but this is not currently possible
+						//because of limitations in BeagleRT_createAuxiliaryTask()
+	//keep track of added active instances
+	objAddrs.push_back(this);//TODO: this line should be in the constructor, but something weird happens if
+	// an instance of NetworkSend is then declared globally: the constructor gets called,
+	// and objAddrs.size()==1 but when you get to setup, objAddrs.size() has reverted back to 0, without
+	// any destructor being called in between ...
+	setChannelNumber(aChannelNumber);
+	setPort(aPort);
+	setServer(aServer);
+	printf("Channel %d is sending messages to : %s:%d at %fHz\n", getChannelNumber(), aServer, aPort, aSampleRate);
+}
+
+
+void NetworkSend::log(float value){ //TODO: add a vectorized version of this method
+	if(channel.index==(NETWORK_AUDIO_BUFFER_SIZE)){ // when the buffer is ready ...
+		channel.readyToBeSent=true;
+		channel.index=channel.headerLength; //reset the counter
+		if(channel.doneOnTime==false){
+			printf("Network buffer underrun. timestamp: %d :-{\n", (int)channel.buffers[!channel.activeBuffer][1]);
+		}
+		channel.timestamp=sampleCount;
+		channel.activeBuffer=!channel.activeBuffer; //switch buffer
+		channel.doneOnTime=false;
+		BeagleRT_scheduleAuxiliaryTask(NetworkSend::transmitAudioTask); //send the buffer
+		//TODO: maybe we should have transmitAudioTask running in a loop instead of scheduling it multiple times?
+	}
+	if(channel.index==channel.headerLength){
+		channel.buffers[channel.activeBuffer][0] = (float)channel.channelNumber; //TODO: this could actually be done just once in setup()
+		channel.buffers[channel.activeBuffer][1]=(float)sampleCount; //timestamp
+		//add here more header fields
+	}
+    channel.buffers[channel.activeBuffer][channel.index++]=value;
+	sampleCount++;
+};
+
+void NetworkSend::setServer(const char *aServer){
+	udpClient.setServer(aServer);
+}
+void NetworkSend::setPort(int aPort){
+	udpClient.setPort(aPort);
+}
+
+void NetworkSend::setChannelNumber(int aChannelNumber){
+	channel.channelNumber=aChannelNumber;
+};
+int NetworkSend::getChannelNumber(){
+	return channel.channelNumber;
+};
+
+void NetworkSend::sendData(){
+	if(channel.readyToBeSent){
+		channel.readyToBeSent=false;
+		udpClient.send(
+			channel.buffers[!channel.activeBuffer],
+			NETWORK_AUDIO_BUFFER_SIZE*sizeof(float)
+		);
+		channel.doneOnTime=true;
+	}
+}
+
+int NetworkSend::getNumInstances(){
+	return objAddrs.size();
+};
+
+Scope::Scope(int aNumChannels):
+		channels(aNumChannels)
+{};
+Scope::~Scope(){};
+
+void Scope::log(int channel, float value){
+	if(channel>=getNumChannels()) //TODO: assert this
+		return;
+	channels[channel].log(value);
+}
+
+void Scope::setup(){
+	setup(44100, 9999, "127.0.0.1");
+}
+
+void Scope::setup(float sampleRate, int aPort, const char* aServer){
+	for(int n=0; n<getNumChannels(); n++){
+		channels[n].setup(sampleRate, n, aPort, aServer);
+	}
+}
+
+int Scope::getNumChannels(){
+	return channels.size();
+}
+
+void Scope::sendData(){
+	NetworkSend::sendAllData();
+}