annotate core/NetworkSend.cpp @ 129:cce58e6ec2a2 scope-refactoring

Added ifdefs USE_JUCE to NetworkSend. Juce part not added yet
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 24 Aug 2015 20:53:26 +0100
parents cdd441a304a9
children ff28e56e5b7e
rev   line source
giuliomoro@112 1 #include <NetworkSend.h>
giuliomoro@111 2
giuliomoro@129 3 #ifdef USE_JUCE
giuliomoro@129 4 #else
giuliomoro@111 5 //initialize the static members of NetworkSend
giuliomoro@111 6 bool NetworkSend::staticConstructed=false;
giuliomoro@111 7 std::vector<NetworkSend*> NetworkSend::objAddrs(0);
giuliomoro@116 8 AuxiliaryTask NetworkSend::sendDataTask=NULL;
giuliomoro@111 9
giuliomoro@129 10 void sendData(){
giuliomoro@111 11 NetworkSend::sendAllData();
giuliomoro@111 12 }
giuliomoro@129 13 void NetworkSend::staticConstructor(){
giuliomoro@129 14 if(staticConstructed==true)
giuliomoro@129 15 return;
giuliomoro@129 16 staticConstructed=true;
giuliomoro@129 17 sendDataTask = BeagleRT_createAuxiliaryTask(::sendData, 95, "sendDataTask"); //TODO: allow variable priority
giuliomoro@129 18 }
giuliomoro@111 19 void NetworkSend::sendAllData(){
giuliomoro@111 20 for(unsigned int n=0; n<NetworkSend::objAddrs.size(); n++){
giuliomoro@111 21 NetworkSend::objAddrs[n]->sendData();
giuliomoro@111 22 }
giuliomoro@111 23 }
giuliomoro@129 24 int NetworkSend::getNumInstances(){
giuliomoro@129 25 return objAddrs.size();
giuliomoro@129 26 }
giuliomoro@129 27 #endif /* USE_JUCE */
giuliomoro@111 28
giuliomoro@111 29 NetworkSend::NetworkSend()
giuliomoro@111 30 {
giuliomoro@111 31 sampleCount = 0;
giuliomoro@111 32 channel.doneOnTime=true;
giuliomoro@111 33 channel.index=channel.headerLength; //leave space for the heading message (channel, timestamp)
giuliomoro@111 34 channel.activeBuffer=0;
giuliomoro@111 35 channel.readyToBeSent=false;
giuliomoro@111 36 }
giuliomoro@116 37
giuliomoro@111 38 NetworkSend::~NetworkSend(){
giuliomoro@111 39 for(unsigned int n=0; n<objAddrs.size(); n++){ //keep track of deleted instances;
giuliomoro@111 40 if(objAddrs[n]==this){
giuliomoro@111 41 objAddrs.erase(objAddrs.begin()+n);
giuliomoro@111 42 break;
giuliomoro@111 43 }
giuliomoro@111 44 }
giuliomoro@111 45 }
giuliomoro@111 46
giuliomoro@129 47 void NetworkSend::setup(float aSampleRate){//TODO: remove this method
giuliomoro@111 48 setup(aSampleRate, 0, 9999, "192.168.7.1");//channelNumber=0
giuliomoro@111 49 }
giuliomoro@129 50
giuliomoro@111 51 void NetworkSend::setup(float aSampleRate, int aChannelNumber, int aPort, const char *aServer){
giuliomoro@111 52 staticConstructor(); //FIXME: ideally this should be in the constructor, but this is not currently possible
giuliomoro@111 53 //because of limitations in BeagleRT_createAuxiliaryTask()
giuliomoro@111 54 //keep track of added active instances
giuliomoro@111 55 objAddrs.push_back(this);//TODO: this line should be in the constructor, but something weird happens if
giuliomoro@111 56 // an instance of NetworkSend is then declared globally: the constructor gets called,
giuliomoro@111 57 // and objAddrs.size()==1 but when you get to setup, objAddrs.size() has reverted back to 0, without
giuliomoro@111 58 // any destructor being called in between ...
giuliomoro@111 59 setChannelNumber(aChannelNumber);
giuliomoro@111 60 setPort(aPort);
giuliomoro@111 61 setServer(aServer);
giuliomoro@120 62 printf("Channel %d is sending messages to: %s:%d at %fHz\n", getChannelNumber(), aServer, aPort, aSampleRate);
giuliomoro@111 63 }
giuliomoro@111 64
giuliomoro@111 65 void NetworkSend::log(float value){ //TODO: add a vectorized version of this method
giuliomoro@111 66 if(channel.index==(NETWORK_AUDIO_BUFFER_SIZE)){ // when the buffer is ready ...
giuliomoro@111 67 channel.readyToBeSent=true;
giuliomoro@111 68 channel.index=channel.headerLength; //reset the counter
giuliomoro@111 69 if(channel.doneOnTime==false){
giuliomoro@111 70 printf("Network buffer underrun. timestamp: %d :-{\n", (int)channel.buffers[!channel.activeBuffer][1]);
giuliomoro@111 71 }
giuliomoro@111 72 channel.activeBuffer=!channel.activeBuffer; //switch buffer
giuliomoro@111 73 channel.doneOnTime=false;
giuliomoro@116 74 BeagleRT_scheduleAuxiliaryTask(NetworkSend::sendDataTask); //send the buffer
giuliomoro@120 75 // TODO: maybe we should have transmitAudioTask running in a loop instead of scheduling it multiple times?
giuliomoro@120 76 // The current solution allows to minimize latency when a single channel is used, as there is no inherent
giuliomoro@120 77 // rt_task_sleep in the thread, as we are signaling it every time.
giuliomoro@120 78 // Although, there is a possible race condition: if the auxiliaryTask is scheduled by channel 0,
giuliomoro@120 79 // it might still be executing when channel 1 schedules it. But if the AuxTask has already skipped
giuliomoro@120 80 // over channel 1, then we are at risk that channel 1 never gets sent.
giuliomoro@111 81 }
giuliomoro@111 82 if(channel.index==channel.headerLength){
giuliomoro@111 83 channel.buffers[channel.activeBuffer][0] = (float)channel.channelNumber; //TODO: this could actually be done just once in setup()
giuliomoro@111 84 channel.buffers[channel.activeBuffer][1]=(float)sampleCount; //timestamp
giuliomoro@111 85 //add here more header fields
giuliomoro@111 86 }
giuliomoro@111 87 channel.buffers[channel.activeBuffer][channel.index++]=value;
giuliomoro@111 88 sampleCount++;
giuliomoro@111 89 };
giuliomoro@111 90
giuliomoro@111 91 void NetworkSend::setServer(const char *aServer){
giuliomoro@111 92 udpClient.setServer(aServer);
giuliomoro@111 93 }
giuliomoro@111 94 void NetworkSend::setPort(int aPort){
giuliomoro@111 95 udpClient.setPort(aPort);
giuliomoro@111 96 }
giuliomoro@111 97
giuliomoro@111 98 void NetworkSend::setChannelNumber(int aChannelNumber){
giuliomoro@111 99 channel.channelNumber=aChannelNumber;
giuliomoro@111 100 };
giuliomoro@111 101 int NetworkSend::getChannelNumber(){
giuliomoro@111 102 return channel.channelNumber;
giuliomoro@111 103 };
giuliomoro@111 104
giuliomoro@111 105 void NetworkSend::sendData(){
giuliomoro@111 106 if(channel.readyToBeSent){
giuliomoro@111 107 channel.readyToBeSent=false;
giuliomoro@111 108 udpClient.send(
giuliomoro@111 109 channel.buffers[!channel.activeBuffer],
giuliomoro@111 110 NETWORK_AUDIO_BUFFER_SIZE*sizeof(float)
giuliomoro@111 111 );
giuliomoro@111 112 channel.doneOnTime=true;
giuliomoro@111 113 }
giuliomoro@111 114 }
giuliomoro@111 115
giuliomoro@129 116 #ifdef USE_JUCE
giuliomoro@129 117 #else
giuliomoro@111 118 Scope::Scope(int aNumChannels):
giuliomoro@111 119 channels(aNumChannels)
giuliomoro@111 120 {};
giuliomoro@111 121 Scope::~Scope(){};
giuliomoro@111 122
giuliomoro@111 123 void Scope::log(int channel, float value){
giuliomoro@111 124 if(channel>=getNumChannels()) //TODO: assert this
giuliomoro@111 125 return;
giuliomoro@111 126 channels[channel].log(value);
giuliomoro@111 127 }
giuliomoro@111 128
giuliomoro@111 129 void Scope::setup(){
giuliomoro@111 130 setup(44100, 9999, "127.0.0.1");
giuliomoro@111 131 }
giuliomoro@111 132
giuliomoro@111 133 void Scope::setup(float sampleRate, int aPort, const char* aServer){
giuliomoro@111 134 for(int n=0; n<getNumChannels(); n++){
giuliomoro@111 135 channels[n].setup(sampleRate, n, aPort, aServer);
giuliomoro@111 136 }
giuliomoro@111 137 }
giuliomoro@111 138
giuliomoro@119 139 void Scope::setPort(int port){
giuliomoro@119 140 for(int n=0; n<getNumChannels(); n++){
giuliomoro@119 141 channels[n].setPort(port);
giuliomoro@119 142 }
giuliomoro@119 143 }
giuliomoro@120 144 void Scope::setPort(int channel, int aPort){
giuliomoro@120 145 channels[channel].setPort(aPort);
giuliomoro@120 146 printf("Channel %d is now sending to port %d\n", channel, aPort);
giuliomoro@119 147 }
giuliomoro@119 148
giuliomoro@111 149 int Scope::getNumChannels(){
giuliomoro@111 150 return channels.size();
giuliomoro@111 151 }
giuliomoro@111 152
giuliomoro@111 153 void Scope::sendData(){
giuliomoro@111 154 NetworkSend::sendAllData();
giuliomoro@111 155 }
giuliomoro@129 156 #endif