root/branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.cpp

Revision 277, 35.1 kB (checked in by jwoithe, 17 years ago)

Start of work leading to MOTU iso transmission.
Fix use of uninitialised local variable in DelayLockedLoop::setIntegrator().

Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2005,2006 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *   Copyright (C) 2006 Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
11  *
12  *   This program is free software {} you can redistribute it and/or modify
13  *   it under the terms of the GNU General Public License as published by
14  *   the Free Software Foundation {} either version 2 of the License, or
15  *   (at your option) any later version.
16  *
17  *   This program is distributed in the hope that it will be useful,
18  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *   GNU General Public License for more details.
21  *
22  *   You should have received a copy of the GNU General Public License
23  *   along with this program {} if not, write to the Free Software
24  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  *
27  *
28  */
29
30
31 #include "MotuStreamProcessor.h"
32 #include "Port.h"
33 #include "MotuPort.h"
34
35 #include <netinet/in.h>
36
37 namespace FreebobStreaming {
38
39 IMPL_DEBUG_MODULE( MotuTransmitStreamProcessor, MotuTransmitStreamProcessor, DEBUG_LEVEL_NORMAL );
40 IMPL_DEBUG_MODULE( MotuReceiveStreamProcessor, MotuReceiveStreamProcessor, DEBUG_LEVEL_NORMAL );
41
42 // A macro to extract specific bits from a native endian quadlet
43 #define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1))
44
45
46 /* transmit */
47 MotuTransmitStreamProcessor::MotuTransmitStreamProcessor(int port, int framerate,
48                 unsigned int event_size)
49         : TransmitStreamProcessor(port, framerate), m_event_size(event_size) {
50
51 }
52
53 MotuTransmitStreamProcessor::~MotuTransmitStreamProcessor() {
54         freebob_ringbuffer_free(m_event_buffer);
55         free(m_tmp_event_buffer);
56 }
57
58 bool MotuTransmitStreamProcessor::init() {
59
60         debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing (%p)...\n");
61         // call the parent init
62         // this has to be done before allocating the buffers,
63         // because this sets the buffersizes from the processormanager
64         if(!TransmitStreamProcessor::init()) {
65                 debugFatal("Could not do base class init (%p)\n",this);
66                 return false;
67         }
68        
69
70         return true;
71 }
72
73 void MotuTransmitStreamProcessor::setVerboseLevel(int l) {
74         setDebugLevel(l); // sets the debug level of the current object
75         TransmitStreamProcessor::setVerboseLevel(l); // also set the level of the base class
76 }
77
78
79 enum raw1394_iso_disposition
80 MotuTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length,
81                       unsigned char *tag, unsigned char *sy,
82                       int cycle, unsigned int dropped, unsigned int max_length) {
83
84         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
85        
86         // signal that we are running
87         // this is to allow the manager to wait untill all streams are up&running
88         // it can take some time before the devices start to transmit.
89         // if we would transmit ourselves, we'd have instant buffer underrun
90         // this works in cooperation with the m_disabled value
91        
92         // TODO: add code here to detect that a stream is running
93         // NOTE: xmit streams are most likely 'always' ready
94         m_running=true;
95        
96         // don't process the stream when it is not enabled.
97         // however, maybe we do have to generate (semi) valid packets
98         if (m_disabled) {
99                 *length = 0;
100                 *tag = 1; // TODO: is this correct for MOTU?
101                 *sy = 0;
102                 return RAW1394_ISO_OK;
103         }
104
105 // FIXME: for now always just return NULL packets
106 *length = 0;
107 *tag = 0;
108 *sy = 0;
109 freebob_ringbuffer_read_advance(m_event_buffer, 6*m_event_size);
110 incrementFrameCounter(6);
111 return RAW1394_ISO_OK;
112        
113     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n");
114        
115         // construct the packet cip
116
117     // TODO: calculate read_size here.
118     // note: an 'event' is one sample from all channels + possibly other midi and control data
119     int nevents=0; // TODO: determine
120         unsigned int read_size=nevents*m_event_size;
121
122     // we read the packet data from a ringbuffer, because of efficiency
123     // that allows us to construct the packets one period at once
124         if ((freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size)) <
125                                 read_size)
126         {
127         /* there is no more data in the ringbuffer */
128         debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",
129                  cycle, m_framecounter, m_handler->getPacketCount());
130        
131         // signal underrun
132         m_xruns++;
133
134         retval=RAW1394_ISO_DEFER; // make raw1394_loop_iterate exit its inner loop
135         *length=0;
136         nevents=0;
137
138     } else {
139         retval=RAW1394_ISO_OK;
140         *length = read_size + 8;
141        
142         // process all ports that should be handled on a per-packet base
143         // this is MIDI for AMDTP (due to the need of DBC, which is lost
144         // when putting the events in the ringbuffer)
145         // for motu this might also be control data, however as control
146         // data isn't time specific I would also include it in the period
147         // based processing
148        
149         int dbc=0;//get this from your packet, if you need it. otherwise change encodePacketPorts
150         if (!encodePacketPorts((quadlet_t *)(data+8), nevents, dbc)) {
151             debugWarning("Problem encoding Packet Ports\n");
152         }
153     }
154    
155     *tag = 1; // TODO: is this correct for MOTU?
156     *sy = 0;
157    
158     // update the frame counter
159     incrementFrameCounter(nevents);
160     // keep this at the end, because otherwise the raw1394_loop_iterate functions inner loop
161     // keeps requesting packets, that are not nescessarily ready
162     if(m_framecounter>(signed int)m_period) {
163        retval=RAW1394_ISO_DEFER;
164     }
165        
166     return retval;
167
168 }
169
170 bool MotuTransmitStreamProcessor::isOnePeriodReady()
171 {
172      // TODO: this is the way you can implement sync
173      //       only when this returns true, one period will be
174      //       transferred to the audio api side.
175      //       you can delay this moment as long as you
176      //       want (provided that there is enough buffer space)
177      
178      // this implementation just waits until there is one period of samples
179      // transmitted from the buffer
180      return (m_framecounter > (signed int)m_period);
181 }
182  
183 bool MotuTransmitStreamProcessor::prefill() {
184     // this is needed because otherwise there is no data to be
185     // sent when the streaming starts
186    
187     int i=m_nb_buffers;
188     while(i--) {
189         if(!transferSilence(m_period)) {
190             debugFatal("Could not prefill transmit stream\n");
191             return false;
192         }
193     }
194    
195     return true;
196    
197 }
198
199 bool MotuTransmitStreamProcessor::reset() {
200
201     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
202
203     // reset the event buffer, discard all content
204     freebob_ringbuffer_reset(m_event_buffer);
205    
206     // reset all non-device specific stuff
207     // i.e. the iso stream and the associated ports
208     if(!TransmitStreamProcessor::reset()) {
209         debugFatal("Could not do base class reset\n");
210         return false;
211     }
212
213     // we should prefill the event buffer
214     if (!prefill()) {
215         debugFatal("Could not prefill buffers\n");
216         return false;   
217     }
218
219     return true;
220 }
221
222 bool MotuTransmitStreamProcessor::prepare() {
223    
224     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
225    
226     // prepare all non-device specific stuff
227     // i.e. the iso stream and the associated ports
228     if(!TransmitStreamProcessor::prepare()) {
229         debugFatal("Could not prepare base class\n");
230         return false;
231     }
232
233         m_PeriodStat.setName("XMT PERIOD");
234         m_PacketStat.setName("XMT PACKET");
235         m_WakeupStat.setName("XMT WAKEUP");
236
237     debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size);
238    
239     // allocate the event buffer
240     unsigned int ringbuffer_size_frames=m_nb_buffers * m_period;
241    
242     if( !(m_event_buffer=freebob_ringbuffer_create(
243         m_event_size * ringbuffer_size_frames))) {
244                 debugFatal("Could not allocate memory event ringbuffer");
245         return false;
246     }
247
248     // allocate the temporary event buffer
249     // this is needed for the efficient transfer() routine
250     // its size has to be equal to one 'event'
251     if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) {
252         debugFatal("Could not allocate temporary event buffer");
253         freebob_ringbuffer_free(m_event_buffer);
254         return false;
255     }
256
257     // set the parameters of ports we can:
258     // we want the audio ports to be period buffered,
259     // and the midi ports to be packet buffered
260     for ( PortVectorIterator it = m_Ports.begin();
261           it != m_Ports.end();
262           ++it )
263     {
264         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
265         if(!(*it)->setBufferSize(m_period)) {
266             debugFatal("Could not set buffer size to %d\n",m_period);
267             return false;
268         }
269        
270        
271         switch ((*it)->getPortType()) {
272             case Port::E_Audio:
273                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
274                     debugFatal("Could not set signal type to PeriodSignalling");
275                     return false;
276                 }
277                
278                 break;
279             case Port::E_Midi:
280                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
281                     debugFatal("Could not set signal type to PacketSignalling");
282                     return false;
283                 }
284                
285                 break;
286                
287             case Port::E_Control:
288                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
289                     debugFatal("Could not set signal type to PeriodSignalling");
290                     return false;
291                 }
292                
293                 break;
294             default:
295                 debugWarning("Unsupported port type specified\n");
296                 break;
297         }
298     }
299
300     // the API specific settings of the ports are already set before
301     // this routine is called, therefore we can init&prepare the ports
302     if(!initPorts()) {
303         debugFatal("Could not initialize ports!\n");
304         return false;
305     }
306
307     if(!preparePorts()) {
308         debugFatal("Could not initialize ports!\n");
309         return false;
310     }
311
312     // we should prefill the event buffer
313     if (!prefill()) {
314         debugFatal("Could not prefill buffers\n");
315         return false;   
316     }
317
318     return true;
319
320 }
321
322 bool MotuTransmitStreamProcessor::transferSilence(unsigned int size) {
323    
324     // this function should tranfer 'size' frames of 'silence' to the event buffer
325     unsigned int write_size=size*m_event_size;
326     char *dummybuffer=(char *)calloc(size,m_event_size);
327
328     transmitSilenceBlock(dummybuffer, size, 0);
329
330     if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) {
331         debugWarning("Could not write to event buffer\n");
332     }
333    
334     free(dummybuffer);
335    
336     return true;
337 }
338
339 bool MotuTransmitStreamProcessor::transfer() {
340     m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/m_event_size);
341
342     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
343     // TODO: improve
344 /* a naive implementation would look like this:
345
346     unsigned int write_size=m_period*m_event_size;
347     char *dummybuffer=(char *)calloc(m_period,m_event_size);
348    
349     transmitBlock(dummybuffer, m_period, 0, 0);
350
351     if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) {
352         debugWarning("Could not write to event buffer\n");
353     }
354
355
356     free(dummybuffer);
357 */
358 /* but we're not that naive anymore... */
359     int xrun;
360     unsigned int offset=0;
361
362 // FIXME: just return until we've got the transmit side of things functional
363 return true;
364
365     freebob_ringbuffer_data_t vec[2];
366     // we received one period of frames
367     // this is period_size*m_event_size of events
368     unsigned int bytes2write=m_period*m_event_size;
369
370     /* write events2write bytes to the ringbuffer
371     *  first see if it can be done in one read.
372     *  if so, ok.
373     *  otherwise write up to a multiple of events directly to the buffer
374     *  then do the buffer wrap around using ringbuffer_write
375     *  then write the remaining data directly to the buffer in a third pass
376     *  Make sure that we cannot end up on a non-cluster aligned position!
377     */
378     while(bytes2write>0) {
379         int byteswritten=0;
380        
381         unsigned int frameswritten=(m_period*m_event_size-bytes2write)/m_event_size;
382         offset=frameswritten;
383        
384         freebob_ringbuffer_get_write_vector(m_event_buffer, vec);
385            
386         if(vec[0].len==0) { // this indicates a full event buffer
387             debugError("XMT: Event buffer overrun in processor %p\n",this);
388             break;
389         }
390            
391         /* if we don't take care we will get stuck in an infinite loop
392         * because we align to a event boundary later
393         * the remaining nb of bytes in one write operation can be
394         * smaller than one event
395         * this can happen because the ringbuffer size is always a power of 2
396         */
397         if(vec[0].len<m_event_size) {
398            
399             // encode to the temporary buffer
400             xrun = transmitBlock(m_tmp_event_buffer, 1, offset);
401            
402             if(xrun<0) {
403                 // xrun detected
404                 debugError("XMT: Frame buffer underrun in processor %p\n",this);
405                 break;
406             }
407                
408             // use the ringbuffer function to write one event
409             // the write function handles the wrap around.
410             freebob_ringbuffer_write(m_event_buffer,
411                          m_tmp_event_buffer,
412                          m_event_size);
413                
414             // we advanced one m_event_size
415             bytes2write-=m_event_size;
416                
417         } else { //
418            
419             if(bytes2write>vec[0].len) {
420                 // align to an event boundary
421                 byteswritten=vec[0].len-(vec[0].len%m_event_size);
422             } else {
423                 byteswritten=bytes2write;
424             }
425                
426             xrun = transmitBlock(vec[0].buf,
427                          byteswritten/m_event_size,
428                          offset);
429            
430             if(xrun<0) {
431                     // xrun detected
432                 debugError("XMT: Frame buffer underrun in processor %p\n",this);
433                 break;
434             }
435
436             freebob_ringbuffer_write_advance(m_event_buffer, byteswritten);
437             bytes2write -= byteswritten;
438         }
439
440         // the bytes2write should always be event aligned
441         assert(bytes2write%m_event_size==0);
442
443     }
444
445     return true;
446 }
447 /*
448  * write received events to the stream ringbuffers.
449  */
450
451 int MotuTransmitStreamProcessor::transmitBlock(char *data,
452                        unsigned int nevents, unsigned int offset)
453 {
454     int problem=0;
455
456     for ( PortVectorIterator it = m_PeriodPorts.begin();
457           it != m_PeriodPorts.end();
458           ++it )
459     {
460         // if this port is disabled, don't process it
461         if((*it)->isDisabled()) {continue;};
462        
463         //FIXME: make this into a static_cast when not DEBUG?
464
465         MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it);
466         assert(pinfo); // this should not fail!!
467
468 /*      This is the AMDTP way, the motu way is different
469         Leaving this in as reference
470        
471         switch(pinfo->getFormat()) {
472        
473        
474         case MotuPortInfo::E_MBLA:
475             if(encodePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
476                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
477                 problem=1;
478             }
479             break;
480         case MotuPortInfo::E_SPDIF: // still unimplemented
481             break;
482         default: // ignore
483             break;
484         }
485 */
486     }
487     return problem;
488
489 }
490
491 int MotuTransmitStreamProcessor::transmitSilenceBlock(char *data,
492                        unsigned int nevents, unsigned int offset)
493 {
494     int problem=0;
495
496     for ( PortVectorIterator it = m_PeriodPorts.begin();
497           it != m_PeriodPorts.end();
498           ++it )
499     {
500
501         //FIXME: make this into a static_cast when not DEBUG?
502
503         MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it);
504         assert(pinfo); // this should not fail!!
505
506 /* this is the same as the non-silence version, except that is doesn't read from the port buffers
507         switch(pinfo->getFormat()) {
508        
509
510         case MotuPortInfo::E_MBLA:
511             if(encodeSilencePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
512                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
513                 problem=1;
514             }
515             break;
516         case MotuPortInfo::E_SPDIF: // still unimplemented
517             break;
518         default: // ignore
519             break;
520         }
521         */
522     }
523     return problem;
524
525 }
526
527 /**
528  * @brief decode a packet for the packet-based ports
529  *
530  * @param data Packet data
531  * @param nevents number of events in data (including events of other ports & port types)
532  * @param dbc DataBlockCount value for this packet
533  * @return true if all successfull
534  */
535 bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
536 {
537     bool ok=true;
538     char byte;
539    
540     quadlet_t *target_event=NULL;
541     int j;
542
543     for ( PortVectorIterator it = m_PacketPorts.begin();
544           it != m_PacketPorts.end();
545           ++it )
546     {
547
548 #ifdef DEBUG
549         MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it);
550         assert(pinfo); // this should not fail!!
551
552         // the only packet type of events for AMDTP is MIDI in mbla
553 //         assert(pinfo->getFormat()==MotuPortInfo::E_Midi);
554 #endif
555        
556         MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);
557        
558         // TODO: decode the midi (or other type) stuff here
559
560     }
561        
562     return ok;
563 }
564
565 /* Left in as reference, this is highly AMDTP related
566
567 basic idea:
568
569 iterate over the ports
570 - get port buffer address
571 - loop over events
572   * pick right sample in event based upon PortInfo
573   * convert sample from Port format (E_Int24, E_Float, ..) to native format
574
575 not that in order to use the 'efficient' transfer method, you have to make sure that
576 you can start from an offset (expressed in frames).
577
578 int MotuTransmitStreamProcessor::encodePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,
579                        unsigned int offset, unsigned int nevents)
580 {
581     unsigned int j=0;
582
583     quadlet_t *target_event;
584
585     target_event=(quadlet_t *)(data + p->getPosition());
586
587     switch(p->getDataType()) {
588         default:
589         case Port::E_Int24:
590             {
591                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
592
593                 assert(nevents + offset <= p->getBufferSize());
594
595                 buffer+=offset;
596
597                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
598                     *target_event = htonl((*(buffer) & 0x00FFFFFF) | 0x40000000);
599                     buffer++;
600                     target_event += m_dimension;
601                 }
602             }
603             break;
604         case Port::E_Float:
605             {
606                 const float multiplier = (float)(0x7FFFFF00);
607                 float *buffer=(float *)(p->getBufferAddress());
608
609                 assert(nevents + offset <= p->getBufferSize());
610
611                 buffer+=offset;
612
613                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
614    
615                     // don't care for overflow
616                     float v = *buffer * multiplier;  // v: -231 .. 231
617                     unsigned int tmp = ((int)v);
618                     *target_event = htonl((tmp >> 8) | 0x40000000);
619                    
620                     buffer++;
621                     target_event += m_dimension;
622                 }
623             }
624             break;
625     }
626
627     return 0;
628 }
629 */
630 /*
631 int MotuTransmitStreamProcessor::encodeSilencePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,
632                        unsigned int offset, unsigned int nevents)
633 {
634     unsigned int j=0;
635
636     quadlet_t *target_event;
637
638     target_event=(quadlet_t *)(data + p->getPosition());
639
640     switch(p->getDataType()) {
641         default:
642         case Port::E_Int24:
643         case Port::E_Float:
644             {
645                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
646                     *target_event = htonl(0x40000000);
647                     target_event += m_dimension;
648                 }
649             }
650             break;
651     }
652
653     return 0;
654 }
655 */
656
657 /* --------------------- RECEIVE ----------------------- */
658
659 MotuReceiveStreamProcessor::MotuReceiveStreamProcessor(int port, int framerate,
660         unsigned int event_size)
661     : ReceiveStreamProcessor(port, framerate), m_event_size(event_size),
662         m_last_cycle_ofs(-1) {
663
664         // Set up the Delay-locked-loop to track audio frequency relative
665         // to the cycle timer.  The seed value is just the difference one
666         // would see if the audio clock was locked to the ieee1394 cycle
667         // timer.
668         // FIXME: the value for omega and coeff[0] are more or less copied
669         // from the test-dll.cpp code.  They need to be understood and
670         // optimised for this process.
671         float omega=6.28*0.001;
672         float coeffs[1];
673         coeffs[0]=1.41*omega;
674         m_sph_ofs_dll = new FreebobUtil::DelayLockedLoop(1, coeffs);
675         m_sph_ofs_dll->setIntegrator(0, 24576000.0/framerate);
676 }
677
678 MotuReceiveStreamProcessor::~MotuReceiveStreamProcessor() {
679         freebob_ringbuffer_free(m_event_buffer);
680         free(m_tmp_event_buffer);
681         delete m_sph_ofs_dll;
682 }
683
684 bool MotuReceiveStreamProcessor::init() {
685
686     // call the parent init
687     // this has to be done before allocating the buffers,
688     // because this sets the buffersizes from the processormanager
689     if(!ReceiveStreamProcessor::init()) {
690         debugFatal("Could not do base class init (%d)\n",this);
691         return false;
692     }
693
694     return true;
695 }
696
697 enum raw1394_iso_disposition
698 MotuReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,
699                   unsigned char channel, unsigned char tag, unsigned char sy,
700                   unsigned int cycle, unsigned int dropped) {
701    
702     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
703
704 // FIXME: just for debugging, print out the sph ofs DLL value
705 // once a second
706 if (cycle==0) {
707   fprintf(stderr, "sph_ofs_dll=%g\n",m_sph_ofs_dll->get());
708 }
709
710     // If the packet length is 8 bytes (ie: just a CIP-like header) there is
711     // no isodata.
712     if (length > 8) {
713         // The iso data blocks from the MOTUs comprise a CIP-like header
714         // followed by a number of events (8 for 1x rates, 16 for 2x rates,
715         // 32 for 4x rates).
716         quadlet_t *quadlet = (quadlet_t *)data;
717         unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size
718         unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits
719         unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes
720         unsigned int n_events = (length-8) / event_length;
721
722         // Don't even attempt to process a packet if it isn't what we expect
723         // from a MOTU
724         if (tag!=1 || fdf_size!=32) {
725                 return RAW1394_ISO_OK;
726         }
727        
728         // Signal that we're running
729         if (n_events) m_running=true;
730
731         // Don't process the stream when it is not enabled.
732         if (m_disabled) {
733                 return RAW1394_ISO_OK;
734         }
735        
736         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n");
737
738         // Add the data payload (events) to the ringbuffer.  We'll just copy
739         // everything including the 4 byte timestamp at the start of each
740         // event (that is, everything except the CIP-like header).  The
741         // demultiplexer can deal with the complexities such as the channel
742         // 24-bit data.
743         unsigned int write_size = length-8;
744         if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size) {
745                 debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",
746                         cycle, m_framecounter, m_handler->getPacketCount());
747                 m_xruns++;
748
749                 retval=RAW1394_ISO_DEFER;
750         } else {
751                 retval=RAW1394_ISO_OK;
752                 // Process all ports that should be handled on a per-packet basis
753                 // This is MIDI for AMDTP (due to the need of DBC)
754                 int dbc = get_bits(ntohl(quadlet[0]), 8, 8);  // Low byte of CIP quadlet 0
755                 if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) {
756                         debugWarning("Problem decoding Packet Ports\n");
757                         retval=RAW1394_ISO_DEFER;
758                 }
759                 // time stamp processing can be done here
760         }
761
762         // update the frame counter
763         incrementFrameCounter(n_events);
764         // keep this at the end, because otherwise the raw1394_loop_iterate functions inner loop
765         // keeps requesting packets without going to the xmit handler, leading to xmit starvation
766         if(m_framecounter>(signed int)m_period) {
767                 retval=RAW1394_ISO_DEFER;
768         }
769        
770     } else { // no events in packet
771         // discard packet
772         // can be important for sync though
773     }
774    
775     return retval;
776 }
777
778 bool MotuReceiveStreamProcessor::isOnePeriodReady() {
779      // TODO: this is the way you can implement sync
780      //       only when this returns true, one period will be
781      //       transferred to the audio api side.
782      //       you can delay this moment as long as you
783      //       want (provided that there is enough buffer space)
784      
785      // this implementation just waits until there is one period of samples
786      // received into the buffer
787     if(m_framecounter > (signed int)m_period) {
788         return true;
789     }
790     return false;
791 }
792
793 void MotuReceiveStreamProcessor::setVerboseLevel(int l) {
794         setDebugLevel(l);
795         ReceiveStreamProcessor::setVerboseLevel(l);
796
797 }
798
799
800 bool MotuReceiveStreamProcessor::reset() {
801
802         debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
803
804         // reset the event buffer, discard all content
805         freebob_ringbuffer_reset(m_event_buffer);
806
807         // reset all non-device specific stuff
808         // i.e. the iso stream and the associated ports
809         if(!ReceiveStreamProcessor::reset()) {
810                 debugFatal("Could not do base class reset\n");
811                 return false;
812         }
813        
814         return true;
815 }
816
817 bool MotuReceiveStreamProcessor::prepare() {
818
819         // prepare all non-device specific stuff
820         // i.e. the iso stream and the associated ports
821         if(!ReceiveStreamProcessor::prepare()) {
822                 debugFatal("Could not prepare base class\n");
823                 return false;
824         }
825
826         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
827
828         m_PeriodStat.setName("RCV PERIOD");
829         m_PacketStat.setName("RCV PACKET");
830         m_WakeupStat.setName("RCV WAKEUP");
831
832     // setup any specific stuff here
833
834         debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size);
835    
836         // allocate the event buffer
837         unsigned int ringbuffer_size_frames=m_nb_buffers * m_period;
838
839         if( !(m_event_buffer=freebob_ringbuffer_create(
840                         m_event_size * ringbuffer_size_frames))) {
841                 debugFatal("Could not allocate memory event ringbuffer");
842                 return false;
843         }
844
845         // allocate the temporary event buffer
846         if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) {
847                 debugFatal("Could not allocate temporary event buffer");
848                 freebob_ringbuffer_free(m_event_buffer);
849                 return false;
850         }
851
852         // set the parameters of ports we can:
853         // we want the audio ports to be period buffered,
854         // and the midi ports to be packet buffered
855         for ( PortVectorIterator it = m_Ports.begin();
856                   it != m_Ports.end();
857                   ++it )
858         {
859                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
860                
861                 if(!(*it)->setBufferSize(m_period)) {
862                         debugFatal("Could not set buffer size to %d\n",m_period);
863                         return false;
864                 }
865
866                 switch ((*it)->getPortType()) {
867                         case Port::E_Audio:
868                                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
869                                         debugFatal("Could not set signal type to PeriodSignalling");
870                                         return false;
871                                 }
872                                 break;
873                         case Port::E_Midi:
874                                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
875                                         debugFatal("Could not set signal type to PacketSignalling");
876                                         return false;
877                                 }
878                                 break;
879                         case Port::E_Control:
880                                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
881                                         debugFatal("Could not set signal type to PeriodSignalling");
882                                         return false;
883                                 }
884                                 break;
885                         default:
886                                 debugWarning("Unsupported port type specified\n");
887                                 break;
888                 }
889
890         }
891
892         // The API specific settings of the ports are already set before
893         // this routine is called, therefore we can init&prepare the ports
894         if(!initPorts()) {
895                 debugFatal("Could not initialize ports!\n");
896                 return false;
897         }
898
899         if(!preparePorts()) {
900                 debugFatal("Could not initialize ports!\n");
901                 return false;
902         }
903        
904         return true;
905
906 }
907
908 bool MotuReceiveStreamProcessor::transfer() {
909
910     // the same idea as the transmit processor
911    
912         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
913        
914 /* another naive section:       
915         unsigned int read_size=m_period*m_event_size;
916         char *dummybuffer=(char *)calloc(m_period,m_event_size);
917         if (freebob_ringbuffer_read(m_event_buffer,(char *)(dummybuffer),read_size) < read_size) {
918                 debugWarning("Could not read from event buffer\n");
919         }
920
921         receiveBlock(dummybuffer, m_period, 0);
922
923         free(dummybuffer);
924 */
925         int xrun;
926         unsigned int offset=0;
927        
928         freebob_ringbuffer_data_t vec[2];
929         // We received one period of frames from each channel.
930         // This is period_size*m_event_size bytes.
931         unsigned int bytes2read = m_period * m_event_size;
932
933         /* Read events2read bytes from the ringbuffer.
934         *  First see if it can be done in one read.  If so, ok.
935         *  Otherwise read up to a multiple of events directly from the buffer
936         *  then do the buffer wrap around using ringbuffer_read
937         *  then read the remaining data directly from the buffer in a third pass
938         *  Make sure that we cannot end up on a non-event aligned position!
939         */
940         while(bytes2read>0) {
941                 unsigned int framesread=(m_period*m_event_size-bytes2read)/m_event_size;
942                 offset=framesread;
943                
944                 int bytesread=0;
945
946                 freebob_ringbuffer_get_read_vector(m_event_buffer, vec);
947                        
948                 if(vec[0].len==0) { // this indicates an empty event buffer
949                         debugError("RCV: Event buffer underrun in processor %p\n",this);
950                         break;
951                 }
952                        
953                 /* if we don't take care we will get stuck in an infinite loop
954                 * because we align to an event boundary later
955                 * the remaining nb of bytes in one read operation can be smaller than one event
956                 * this can happen because the ringbuffer size is always a power of 2
957                         */
958                 if(vec[0].len<m_event_size) {
959                         // use the ringbuffer function to read one event
960                         // the read function handles wrap around
961                         freebob_ringbuffer_read(m_event_buffer,m_tmp_event_buffer,m_event_size);
962
963                         xrun = receiveBlock(m_tmp_event_buffer, 1, offset);
964                                
965                         if(xrun<0) {
966                                 // xrun detected
967                                 debugError("RCV: Frame buffer overrun in processor %p\n",this);
968                                 break;
969                         }
970                                
971                         // We advanced one m_event_size
972                         bytes2read-=m_event_size;
973                                
974                 } else { //
975                        
976                         if(bytes2read>vec[0].len) {
977                                         // align to an event boundary
978                                 bytesread=vec[0].len-(vec[0].len%m_event_size);
979                         } else {
980                                 bytesread=bytes2read;
981                         }
982                                
983                         xrun = receiveBlock(vec[0].buf, bytesread/m_event_size, offset);
984                                
985                         if(xrun<0) {
986                                 // xrun detected
987                                 debugError("RCV: Frame buffer overrun in processor %p\n",this);
988                                 break;
989                         }
990
991                         freebob_ringbuffer_read_advance(m_event_buffer, bytesread);
992                         bytes2read -= bytesread;
993                 }
994                        
995                 // the bytes2read should always be event aligned
996                 assert(bytes2read%m_event_size==0);
997         }
998
999         return true;
1000 }
1001
1002 /**
1003  * \brief write received events to the port ringbuffers.
1004  */
1005 int MotuReceiveStreamProcessor::receiveBlock(char *data,
1006                                            unsigned int nevents, unsigned int offset)
1007 {
1008         int problem=0;
1009
1010         /* Push cycle offset differences from each event's SPH into the DLL.
1011          * If this is the very first block received, use the first event to
1012          * initialise the last cycle offset.
1013          * FIXME: it might be best to use differences only within the given
1014          * block rather than keeping a store of the last cycle offset.
1015          * Otherwise in the event of a lost incoming packet the DLL will
1016          * have an abnormally large value sent to it.  Perhaps this doesn't
1017          * matter?
1018          */
1019         unsigned int ev;
1020         signed int sph_ofs = ntohl(*(quadlet_t *)data) & 0xfff;
1021         if (m_last_cycle_ofs < 0) {
1022                 m_last_cycle_ofs = sph_ofs-m_sph_ofs_dll->get();
1023         }
1024         for (ev=0; ev<nevents; ev++) {
1025                 sph_ofs = ntohl(*(quadlet_t *)(data+ev*m_event_size)) & 0xfff;
1026                 m_sph_ofs_dll->put((m_last_cycle_ofs<sph_ofs)?
1027                         sph_ofs-m_last_cycle_ofs:sph_ofs+3072-m_last_cycle_ofs);
1028                 m_last_cycle_ofs = sph_ofs;
1029         }
1030
1031         for ( PortVectorIterator it = m_PeriodPorts.begin();
1032           it != m_PeriodPorts.end();
1033           ++it ) {
1034                 if((*it)->isDisabled()) {continue;};
1035
1036                 //FIXME: make this into a static_cast when not DEBUG?
1037                 Port *port=dynamic_cast<Port *>(*it);
1038                
1039                 switch(port->getPortType()) {
1040                
1041                 case Port::E_Audio:
1042                         if(decodeMBLAEventsToPort(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
1043                                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str());
1044                                 problem=1;
1045                         }
1046                         break;
1047                 // midi is a packet based port, don't process
1048                 //      case MotuPortInfo::E_Midi:
1049                 //              break;
1050
1051                 default: // ignore
1052                         break;
1053                 }
1054         }
1055         return problem;
1056 }
1057
1058 /**
1059  * @brief decode a packet for the packet-based ports
1060  *
1061  * @param data Packet data
1062  * @param nevents number of events in data (including events of other ports & port types)
1063  * @param dbc DataBlockCount value for this packet
1064  * @return true if all successfull
1065  */
1066 bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
1067 {
1068         bool ok=true;
1069        
1070         quadlet_t *target_event=NULL;
1071         int j;
1072        
1073         for ( PortVectorIterator it = m_PacketPorts.begin();
1074           it != m_PacketPorts.end();
1075           ++it ) {
1076
1077 #ifdef DEBUG
1078                 MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it);
1079                 assert(pinfo); // this should not fail!!
1080
1081                 // the only packet type of events for AMDTP is MIDI in mbla
1082 //              assert(pinfo->getFormat()==MotuPortInfo::E_Midi);
1083 #endif
1084                 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);
1085                
1086
1087         // do decoding here
1088
1089         }
1090        
1091         return ok;
1092 }
1093
1094 signed int MotuReceiveStreamProcessor::decodeMBLAEventsToPort(MotuAudioPort *p,
1095                 quadlet_t *data, unsigned int offset, unsigned int nevents)
1096 {
1097         unsigned int j=0;
1098
1099 //      printf("****************\n");
1100 //      hexDumpQuadlets(data,m_dimension*4);
1101 //      printf("****************\n");
1102
1103         // Use char here since a port's source address won't necessarily be
1104         // aligned; use of an unaligned quadlet_t may cause issues on certain
1105         // architectures.
1106         unsigned char *src_data;
1107         src_data = (unsigned char *)data + p->getPosition();
1108
1109         switch(p->getDataType()) {
1110                 default:
1111                 case Port::E_Int24:
1112                         {
1113                                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
1114
1115                                 assert(nevents + offset <= p->getBufferSize());
1116
1117                                 buffer+=offset;
1118
1119                                 for(j = 0; j < nevents; j += 1) { // Decode nsamples
1120                                         *buffer = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
1121                                         // Sign-extend highest bit of 24-bit int.
1122                                         // FIXME: this isn't strictly needed since E_Int24 is a 24-bit,
1123                                         // but doing so shouldn't break anything and makes the data
1124                                         // easier to deal with during debugging.
1125                                         if (*src_data & 0x80)
1126                                                 *buffer |= 0xff000000;
1127
1128                                         buffer++;
1129                                         src_data+=m_event_size;
1130                                 }
1131                         }
1132                         break;
1133                 case Port::E_Float:
1134                         {
1135                                 const float multiplier = 1.0f / (float)(0x7FFFFF);
1136                                 float *buffer=(float *)(p->getBufferAddress());
1137
1138                                 assert(nevents + offset <= p->getBufferSize());
1139
1140                                 buffer+=offset;
1141
1142                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
1143        
1144                                         unsigned int v = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
1145
1146                                         // sign-extend highest bit of 24-bit int
1147                                         int tmp = (int)(v << 8) / 256;
1148                
1149                                         *buffer = tmp * multiplier;
1150                                
1151                                         buffer++;
1152                                         src_data+=m_event_size;
1153                                 }
1154                         }
1155                         break;
1156         }
1157
1158         return 0;
1159 }
1160
1161 signed int MotuReceiveStreamProcessor::setEventSize(unsigned int size) {
1162         m_event_size = size;
1163         return 0;
1164 }
1165
1166 unsigned int MotuReceiveStreamProcessor::getEventSize(void) {
1167 //
1168 // Return the size of a single event sent by the MOTU as part of an iso
1169 // data packet in bytes.
1170 //
1171         return m_event_size;
1172 }
1173                
1174 } // end of namespace FreebobStreaming
Note: See TracBrowser for help on using the browser.