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

Revision 307, 43.2 kB (checked in by jwoithe, 18 years ago)

Minor source code cleanups. No functional changes.

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 <math.h>
36
37 #include <netinet/in.h>
38
39 namespace FreebobStreaming {
40
41 IMPL_DEBUG_MODULE( MotuTransmitStreamProcessor, MotuTransmitStreamProcessor, DEBUG_LEVEL_NORMAL );
42 IMPL_DEBUG_MODULE( MotuReceiveStreamProcessor, MotuReceiveStreamProcessor, DEBUG_LEVEL_NORMAL );
43
44 // Set to 1 to enable the generation of a 1 kHz test tone in analog output 1
45 #define TESTTONE 1
46
47 // A macro to extract specific bits from a native endian quadlet
48 #define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1))
49
50 /* transmit */
51 MotuTransmitStreamProcessor::MotuTransmitStreamProcessor(int port, int framerate,
52                 unsigned int event_size)
53         : TransmitStreamProcessor(port, framerate), m_event_size(event_size),
54         m_tx_dbc(0), m_cycle_count(-1), m_cycle_ofs(0.0), m_next_cycle(-1),
55         m_ticks_per_frame(NULL), m_closedown_count(-1), m_streaming_active(0) {
56 }
57
58 MotuTransmitStreamProcessor::~MotuTransmitStreamProcessor() {
59         freebob_ringbuffer_free(m_event_buffer);
60         free(m_tmp_event_buffer);
61 }
62
63 bool MotuTransmitStreamProcessor::init() {
64
65         debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing (%p)...\n");
66         // call the parent init
67         // this has to be done before allocating the buffers,
68         // because this sets the buffersizes from the processormanager
69         if(!TransmitStreamProcessor::init()) {
70                 debugFatal("Could not do base class init (%p)\n",this);
71                 return false;
72         }
73         m_next_cycle = -1;
74         m_closedown_count = -1;
75         m_streaming_active = 0;
76         m_cycle_count = -1;
77         m_cycle_ofs = 0.0;
78
79         return true;
80 }
81
82 void MotuTransmitStreamProcessor::setVerboseLevel(int l) {
83         setDebugLevel(l); // sets the debug level of the current object
84         TransmitStreamProcessor::setVerboseLevel(l); // also set the level of the base class
85 }
86
87
88 enum raw1394_iso_disposition
89 MotuTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length,
90                       unsigned char *tag, unsigned char *sy,
91                       int cycle, unsigned int dropped, unsigned int max_length) {
92
93 // FIXME: the actual delays in the system need to be worked out so
94 // we can get this thing synchronised.  For now this seems to work.
95 #define CYCLE_DELAY 1
96
97         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
98         quadlet_t *quadlet = (quadlet_t *)data;
99         signed int i;
100         signed int unwrapped_cycle = cycle;
101
102         // Signal that streaming is still active
103         m_streaming_active = 1;
104
105         // The MOTU transmit stream is 'always' ready
106         m_running = true;
107        
108         // Initialise the cycle counter if this is the first time
109         // iso data has been requested.
110         if (!m_disabled && m_cycle_count<0) {
111                 m_cycle_count = cycle;
112                 m_cycle_ofs = 0.0;
113         }
114
115         // Do housekeeping expected for all packets sent to the MOTU, even
116         // for packets containing no audio data.
117         *sy = 0x00;
118         *tag = 1;      // All MOTU packets have a CIP-like header
119
120         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n");
121
122         // Size of a single data frame in quadlets
123         unsigned dbs = m_event_size / 4;
124
125         // The number of events expected by the MOTU is solely dependent on
126         // the current sample rate.  An 'event' is one sample from all channels
127         // plus possibly other midi and control data.
128         signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32);
129
130         // Size of data to read from the event buffer, in bytes.
131         unsigned int read_size = n_events * m_event_size;
132
133         // Detect a missed cycle and attempt to "catch up".
134         if (!m_disabled && m_next_cycle>=0 && cycle!=m_next_cycle) {
135                 float ftmp;
136                 signed int ccount = m_next_cycle;
137                 debugOutput(DEBUG_LEVEL_VERBOSE, "tx cycle miss: %d requested, %d expected\n",cycle,m_next_cycle);
138
139                 while (ccount!=cycle) {
140                         unwrapped_cycle = ccount;
141                         if (m_cycle_count-ccount > 7900)
142                                 unwrapped_cycle += 8000;
143
144                         if (unwrapped_cycle < m_cycle_count) {
145                                 if (++ccount == 8000)
146                                         ccount = 0;
147                                 continue;
148                         }
149                         // Advance buffers and counters as if this cycle had been dealt with
150                         m_tx_dbc += n_events;
151                         incrementFrameCounter(n_events);
152
153                         ftmp = m_cycle_ofs+n_events*(*m_ticks_per_frame);
154                         m_cycle_count += (unsigned int)ftmp/3072;
155                         m_cycle_count %= 8000;
156                         m_cycle_ofs = fmod(ftmp, 3072);
157
158                         if (++ccount == 8000)
159                                 ccount = 0;
160
161                         // Also advance the event buffer to keep things in sync
162                         freebob_ringbuffer_read_advance(m_event_buffer,read_size);
163                 }
164                 m_tx_dbc &= 0xff;
165                 debugOutput(DEBUG_LEVEL_VERBOSE, "  resuming with cyclecount=%d, cycleofs=%g (ticksperfame=%g)\n",
166                         m_cycle_count, m_cycle_ofs, *m_ticks_per_frame);
167
168                 m_next_cycle = cycle;
169         }
170
171
172         if (!m_disabled) {
173                 if (++m_next_cycle >= 8000)
174                         m_next_cycle -= 8000;
175         } else
176                 m_next_cycle = -1;
177
178         // Deal cleanly with potential wrap-around cycle counter conditions
179         unwrapped_cycle = cycle;
180         if (m_cycle_count-cycle > 7900)
181                 unwrapped_cycle += 8000;
182
183         // Increment the dbc (data block count).  This is only done if the
184         // packet will contain events - that is, we are due to send some
185         // data.  Otherwise a pad packet is sent which contains the DBC of
186         // the previously sent packet.  This regime also means that the very
187         // first packet containing data will have a DBC of n_events, which
188         // matches what is observed from other systems.
189         if (!m_disabled && unwrapped_cycle>=m_cycle_count) {
190                 m_tx_dbc += n_events;
191                 if (m_tx_dbc > 0xff)
192                         m_tx_dbc -= 0x100;
193         }
194
195         // construct the packet CIP-like header.  Even if this is a data-less
196         // packet the dbs field is still set as if there were data blocks
197         // present.  For data-less packets the dbc is the same as the previously
198         // transmitted block.
199         *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16));
200         quadlet++;
201         *quadlet = htonl(0x8222ffff);
202         quadlet++;
203         *length = 8;
204
205         // If the stream is disabled or the MOTU transmission cycle count is
206         // ahead of the ieee1394 cycle timer, we send a data-less packet
207         // with only the 8 byte CIP-like header set up previously.
208         if (m_disabled || unwrapped_cycle<m_cycle_count) {
209                 return RAW1394_ISO_OK;
210         }
211
212         // In the disabled state simply zero all data sent to the MOTU.  If
213         // a stream of empty packets are sent once iso streaming is enabled
214         // the MOTU tends to emit high-pitched audio (approx 10 kHz) for
215         // some reason.  This is not completely sufficient, however (zeroed
216         // packets must also be sent on iso closedown).
217
218         // FIXME: Currently we simply send empty packets to the MOTU when
219         // the stream is disabled so the "m_disabled == 0" code is never
220         // executed.  However, this may change in future so it's left in
221         // for the moment for reference.
222         // FIXME: Currently we don't read the buffer at all during closedown.
223         // We could (and silently junk the contents) if it turned out to be
224         // more helpful.
225         if (!m_disabled && m_closedown_count<0) {
226                 // We read the packet data from a ringbuffer because of
227                 // efficiency; it allows us to construct the packets one
228                 // period at once.
229                 i = freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size) <
230                         read_size;
231         } else {
232                 memset(data+8, 0, read_size);
233                 i = 0;
234         }
235         if (i == 1) {
236                 /* there is no more data in the ringbuffer */
237                 debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",
238                         cycle, m_framecounter, m_handler->getPacketCount());
239
240                 // signal underrun
241                 m_xruns++;
242
243                 retval=RAW1394_ISO_DEFER; // make raw1394_loop_iterate exit its inner loop
244                 n_events = 0;
245
246         } else {
247                 retval=RAW1394_ISO_OK;
248                 *length += read_size;
249
250                 // FIXME: if we choose to read the buffer even during closedown,
251                 // here is where the data is silenced.
252                 //   if (m_closedown_count >= 0)
253                 //     memset(data+8, 0, read_size);
254                 if (m_closedown_count > 0)
255                         m_closedown_count--;
256
257                 // Set up each frames's SPH.  Note that the (int) typecast
258                 // appears to do rounding.
259                 //
260                 // CYCLE_DELAY accounts for the delay between the cycle
261                 // audio is sent in and when the MOTU can actually play
262                 // that audio.  The SPH timestamp must account for this
263                 // so it doesn't demand to be played before it's possible.
264                 // For the duration of the event loop, account for the
265                 // CYCLE_DELAY within m_cycle_count to save having to wrap
266                 // (m_cycle_count+CYCLE_DELAY) and m_cycle_count separately
267                 // within the event loop.  Once the loop is finished we
268                 // reset m_cyle_count to once again refer to the send
269                 // cycle rather than the audio presentation cycle.
270                 //
271                 // This seemingly messy treatment saves one modulo operation
272                 // per loop iteration.  Since the loop count ranges from 8
273                 // (for 1x sample rates) to 32 there are considerable
274                 // savings to be made even at 1x rates.
275                 if ((m_cycle_count+=CYCLE_DELAY) >= 8000)
276                         m_cycle_count -= 8000;
277                 for (i=0; i<n_events; i++, quadlet += dbs) {
278                         *quadlet = htonl( (m_cycle_count<<12) + (int)m_cycle_ofs);
279 #if TESTTONE
280                         // FIXME: remove this hacked in 1 kHz test signal to
281                         // analog-1 when testing is complete.  Note that the tone is
282                         // *never* added during closedown.
283                         if (m_closedown_count<0) {
284                                 static signed int a_cx = 0;
285                                 signed int val;
286                                 val = (int)(0x7fffff*sin(1000.0*2.0*M_PI*(a_cx/24576000.0)));
287                                 if ((a_cx+=512) >= 24576000) {
288                                         a_cx -= 24576000;
289                                 }
290                                 *(data+8+i*m_event_size+16) = (val >> 16) & 0xff;
291                                 *(data+8+i*m_event_size+17) = (val >> 8) & 0xff;
292                                 *(data+8+i*m_event_size+18) = val & 0xff;
293                         }
294 #endif
295                         if ((m_cycle_ofs+=*m_ticks_per_frame) >= 3072) {
296                                 m_cycle_ofs -= 3072;
297                                 if (++m_cycle_count > 7999)
298                                         m_cycle_count -= 8000;
299                         }
300                 }
301                 // Reset m_cycle_count to the send cycle
302                 if ((m_cycle_count-=CYCLE_DELAY) < 0)
303                         m_cycle_count += 8000;
304
305                 // Process all ports that should be handled on a per-packet base
306                 // this is MIDI for AMDTP (due to the need of DBC, which is lost
307                 // when putting the events in the ringbuffer)
308                 // for motu this might also be control data, however as control
309                 // data isn't time specific I would also include it in the period
310                 // based processing
311        
312                 // FIXME: m_tx_dbc probably needs to be initialised to a non-zero
313                 // value somehow so MIDI sync is possible.  For now we ignore
314                 // this issue.
315                 if (!encodePacketPorts((quadlet_t *)(data+8), n_events, m_tx_dbc)) {
316                         debugWarning("Problem encoding Packet Ports\n");
317                 }
318         }
319    
320         // Update the frame counter
321         incrementFrameCounter(n_events);
322
323         // Keep this at the end, because otherwise the raw1394_loop_iterate
324         // functions inner loop keeps requesting packets, that are not
325         // nescessarily ready
326
327 // Amdtp has this commented out
328         if (m_framecounter > (signed int)m_period) {
329                 retval=RAW1394_ISO_DEFER;
330         }
331        
332         return retval;
333 }
334
335 bool MotuTransmitStreamProcessor::isOnePeriodReady() {
336         // TODO: this is the way you can implement sync
337         //       only when this returns true, one period will be
338         //       transferred to the audio api side.
339         //       you can delay this moment as long as you
340         //       want (provided that there is enough buffer space)
341        
342         // this implementation just waits until there is one period of samples
343         // transmitted from the buffer
344
345 // Amdtp has this commented out and simply return true.
346         return (m_framecounter > (signed int)m_period);
347 //      return true;
348 }
349  
350 bool MotuTransmitStreamProcessor::prefill() {
351         // this is needed because otherwise there is no data to be
352         // sent when the streaming starts
353    
354         int i = m_nb_buffers;
355         while (i--) {
356                 if(!transferSilence(m_period)) {
357                         debugFatal("Could not prefill transmit stream\n");
358                         return false;
359                 }
360         }
361         return true;
362 }
363
364 bool MotuTransmitStreamProcessor::reset() {
365
366         debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
367
368         // reset the event buffer, discard all content
369         freebob_ringbuffer_reset(m_event_buffer);
370    
371         // reset all non-device specific stuff
372         // i.e. the iso stream and the associated ports
373         if (!TransmitStreamProcessor::reset()) {
374                 debugFatal("Could not do base class reset\n");
375                 return false;
376         }
377
378         // we should prefill the event buffer
379         if (!prefill()) {
380                 debugFatal("Could not prefill buffers\n");
381                 return false;   
382         }
383
384         m_next_cycle = -1;
385         m_closedown_count = -1;
386         m_streaming_active = 0;
387         m_cycle_count = -1;
388         m_cycle_ofs = 0.0;
389
390         return true;
391 }
392
393 bool MotuTransmitStreamProcessor::prepare() {
394    
395         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
396    
397         // prepare all non-device specific stuff
398         // i.e. the iso stream and the associated ports
399         if (!TransmitStreamProcessor::prepare()) {
400                 debugFatal("Could not prepare base class\n");
401                 return false;
402         }
403
404         m_PeriodStat.setName("XMT PERIOD");
405         m_PacketStat.setName("XMT PACKET");
406         m_WakeupStat.setName("XMT WAKEUP");
407
408         debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size);
409    
410         // allocate the event buffer
411         unsigned int ringbuffer_size_frames=m_nb_buffers * m_period;
412    
413         if( !(m_event_buffer=freebob_ringbuffer_create(
414           m_event_size * ringbuffer_size_frames))) {
415                 debugFatal("Could not allocate memory event ringbuffer");
416                 return false;
417         }
418
419         // Allocate the temporary event buffer.  This is needed for the
420         // efficient transfer() routine.  Its size has to be equal to one
421         // 'event'.
422         if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) {
423                 debugFatal("Could not allocate temporary event buffer");
424                 freebob_ringbuffer_free(m_event_buffer);
425                 return false;
426         }
427
428         // Set the parameters of ports we can: we want the audio ports to be
429         // period buffered, and the midi ports to be packet buffered.
430         for ( PortVectorIterator it = m_Ports.begin();
431           it != m_Ports.end();
432           ++it ) {
433                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
434                 if(!(*it)->setBufferSize(m_period)) {
435                         debugFatal("Could not set buffer size to %d\n",m_period);
436                         return false;
437                 }
438
439                 switch ((*it)->getPortType()) {
440                 case Port::E_Audio:
441                         if (!(*it)->setSignalType(Port::E_PeriodSignalled)) {
442                                 debugFatal("Could not set signal type to PeriodSignalling");
443                                 return false;
444                         }
445                         break;
446
447                 case Port::E_Midi:
448                         if (!(*it)->setSignalType(Port::E_PacketSignalled)) {
449                                 debugFatal("Could not set signal type to PacketSignalling");
450                                 return false;
451                         }
452                         break;
453                
454                 case Port::E_Control:
455                         if (!(*it)->setSignalType(Port::E_PeriodSignalled)) {
456                                 debugFatal("Could not set signal type to PeriodSignalling");
457                                 return false;
458                         }
459                         break;
460
461                 default:
462                         debugWarning("Unsupported port type specified\n");
463                         break;
464                 }
465         }
466
467         // The API specific settings of the ports are already set before
468         // this routine is called, therefore we can init&prepare the ports
469         if (!initPorts()) {
470                 debugFatal("Could not initialize ports!\n");
471                 return false;
472         }
473
474         if(!preparePorts()) {
475                 debugFatal("Could not initialize ports!\n");
476                 return false;
477         }
478
479         // We should prefill the event buffer
480         if (!prefill()) {
481                 debugFatal("Could not prefill buffers\n");
482                 return false;   
483         }
484
485         return true;
486 }
487
488 bool MotuTransmitStreamProcessor::transferSilence(unsigned int size) {
489    
490         // This function should tranfer 'size' frames of 'silence' to the event buffer
491         unsigned int write_size=size*m_event_size;
492         char *dummybuffer=(char *)calloc(size,m_event_size);
493
494         transmitSilenceBlock(dummybuffer, size, 0);
495
496         if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) {
497                 debugWarning("Could not write to event buffer\n");
498         }
499
500         free(dummybuffer);
501
502         return true;
503 }
504
505 /**
506  * \brief write events queued for transmission from the port ringbuffers
507  * to the event buffer.
508  */
509 bool MotuTransmitStreamProcessor::transfer() {
510         m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/m_event_size);
511
512         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
513         // TODO: improve
514 /* a naive implementation would look like this:
515
516         unsigned int write_size=m_period*m_event_size;
517         char *dummybuffer=(char *)calloc(m_period,m_event_size);
518
519         transmitBlock(dummybuffer, m_period, 0, 0);
520
521         if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) {
522                 debugWarning("Could not write to event buffer\n");
523         }
524
525         free(dummybuffer);
526 */
527 /* but we're not that naive anymore... */
528         int xrun;
529         unsigned int offset=0;
530
531         freebob_ringbuffer_data_t vec[2];
532         // There is one period of frames to transfer.  This is
533         // period_size*m_event_size of events.
534         unsigned int bytes2write=m_period*m_event_size;
535
536         /* Write bytes2write bytes to the event ringbuffer.  First see if it can
537          * be done in one write; if so, ok.
538          * Otherwise write up to a multiple of events directly to the buffer
539          * then do the buffer wrap around using ringbuffer_write.  Then
540          * write the remaining data directly to the buffer in a third pass.
541          * Make sure that we cannot end up on a non-cluster aligned
542          * position!
543          */
544         while(bytes2write>0) {
545                 int byteswritten=0;
546        
547                 unsigned int frameswritten=(m_period*m_event_size-bytes2write)/m_event_size;
548                 offset=frameswritten;
549
550                 freebob_ringbuffer_get_write_vector(m_event_buffer, vec);
551
552                 if (vec[0].len==0) { // this indicates a full event buffer
553                         debugError("XMT: Event buffer overrun in processor %p\n",this);
554                         break;
555                 }
556
557                 /* If we don't take care we will get stuck in an infinite
558                  * loop because we align to a event boundary later.  The
559                  * remaining nb of bytes in one write operation can be
560                  * smaller than one event; this can happen because the
561                  * ringbuffer size is always a power of 2.
562                  */
563                 if(vec[0].len<m_event_size) {
564            
565                         // encode to the temporary buffer
566                         xrun = transmitBlock(m_tmp_event_buffer, 1, offset);
567            
568                         if (xrun<0) {
569                                 // xrun detected
570                                 debugError("XMT: Frame buffer underrun in processor %p\n",this);
571                                 break;
572                         }
573
574                         // Use the ringbuffer function to write one event.
575                         // The write function handles the wrap around.
576                         freebob_ringbuffer_write(m_event_buffer,
577                                 m_tmp_event_buffer, m_event_size);
578                
579                         // we advanced one m_event_size
580                         bytes2write-=m_event_size;
581                
582                 } else {
583            
584                         if (bytes2write>vec[0].len) {
585                                 // align to an event boundary
586                                 byteswritten=vec[0].len-(vec[0].len%m_event_size);
587                         } else {
588                                 byteswritten=bytes2write;
589                         }
590
591                         xrun = transmitBlock(vec[0].buf,
592                                 byteswritten/m_event_size, offset);
593            
594                         if (xrun<0) {
595                                 // xrun detected
596                                 debugError("XMT: Frame buffer underrun in processor %p\n",this);
597                                 break;
598                         }
599
600                         freebob_ringbuffer_write_advance(m_event_buffer, byteswritten);
601                         bytes2write -= byteswritten;
602                 }
603
604                 // the bytes2write should always be event aligned
605                 assert(bytes2write%m_event_size==0);
606         }
607
608         return true;
609 }
610 /*
611  * write received events to the stream ringbuffers.
612  */
613
614 int MotuTransmitStreamProcessor::transmitBlock(char *data,
615                        unsigned int nevents, unsigned int offset) {
616         signed int problem=0;
617         unsigned int i;
618
619         // FIXME: ensure the MIDI and control streams are all zeroed until
620         // such time as they are fully implemented.
621         for (i=0; i<nevents; i++) {
622                 memset(data+4+i*m_event_size, 0x00, 6);
623         }
624
625         for ( PortVectorIterator it = m_PeriodPorts.begin();
626           it != m_PeriodPorts.end();
627           ++it ) {
628                 // If this port is disabled, don't process it
629                 if((*it)->isDisabled()) {continue;};
630        
631                 //FIXME: make this into a static_cast when not DEBUG?
632                 Port *port=dynamic_cast<Port *>(*it);
633                
634                 switch(port->getPortType()) {
635                
636                 case Port::E_Audio:
637                         if (encodePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
638                                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
639                                 problem=1;
640                         }
641                         break;
642                 // midi is a packet based port, don't process
643                 //      case MotuPortInfo::E_Midi:
644                 //              break;
645
646                 default: // ignore
647                         break;
648                 }
649         }
650         return problem;
651 }
652
653 int MotuTransmitStreamProcessor::transmitSilenceBlock(char *data,
654                        unsigned int nevents, unsigned int offset) {
655         // This is the same as the non-silence version, except that is
656         // doesn't read from the port buffers.
657
658         int problem=0;
659
660         for ( PortVectorIterator it = m_PeriodPorts.begin();
661           it != m_PeriodPorts.end();
662           ++it ) {
663                 //FIXME: make this into a static_cast when not DEBUG?
664                 Port *port=dynamic_cast<Port *>(*it);
665                
666                 switch(port->getPortType()) {
667                
668                 case Port::E_Audio:
669                         if (encodeSilencePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
670                                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
671                                 problem=1;
672                         }
673                         break;
674                 // midi is a packet based port, don't process
675                 //      case MotuPortInfo::E_Midi:
676                 //              break;
677
678                 default: // ignore
679                         break;
680                 }
681         }
682         return problem;
683 }
684
685 /**
686  * @brief decode a packet for the packet-based ports
687  *
688  * @param data Packet data
689  * @param nevents number of events in data (including events of other ports & port types)
690  * @param dbc DataBlockCount value for this packet
691  * @return true if all successfull
692  */
693 bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
694 {
695     bool ok=true;
696     char byte;
697    
698     quadlet_t *target_event=NULL;
699     int j;
700
701     for ( PortVectorIterator it = m_PacketPorts.begin();
702           it != m_PacketPorts.end();
703           ++it )
704     {
705
706 #ifdef DEBUG
707         MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it);
708         assert(pinfo); // this should not fail!!
709
710         // the only packet type of events for AMDTP is MIDI in mbla
711 //         assert(pinfo->getFormat()==MotuPortInfo::E_Midi);
712 #endif
713        
714         MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);
715        
716         // TODO: decode the midi (or other type) stuff here
717
718     }
719        
720     return ok;
721 }
722
723 int MotuTransmitStreamProcessor::encodePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,
724                        unsigned int offset, unsigned int nevents) {
725 // Encodes nevents worth of data from the given port into the given buffer.  The
726 // format of the buffer is precisely that which will be sent to the MOTU.
727 // The basic idea:
728 //   iterate over the ports
729 //     * get port buffer address
730 //     * loop over events
731 //         - pick right sample in event based upon PortInfo
732 //         - convert sample from Port format (E_Int24, E_Float, ..) to MOTU
733 //           native format
734 //
735 // We include the ability to start the transfer from the given offset within
736 // the port (expressed in frames) so the 'efficient' transfer method can be
737 // utilised.
738
739         unsigned int j=0;
740
741         // Use char here since the target address won't necessarily be
742         // aligned; use of an unaligned quadlet_t may cause issues on certain
743         // architectures.  Besides, the target (data going directly to the MOTU)
744         // isn't structured in quadlets anyway; it mainly consists of packed
745         // 24-bit integers.
746         unsigned char *target;
747         target = (unsigned char *)data + p->getPosition();
748
749         switch(p->getDataType()) {
750                 default:
751                 case Port::E_Int24:
752                         {
753                                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
754
755                                 assert(nevents + offset <= p->getBufferSize());
756
757                                 // Offset is in frames, but each port is only a single
758                                 // channel, so the number of frames is the same as the
759                                 // number of quadlets to offset (assuming the port buffer
760                                 // uses one quadlet per sample, which is the case currently).
761                                 buffer+=offset;
762
763                                 for(j = 0; j < nevents; j += 1) { // Decode nsamples
764                                         *target = (*buffer >> 16) & 0xff;
765                                         *(target+1) = (*buffer >> 8) & 0xff;
766                                         *(target+2) = (*buffer) & 0xff;
767
768                                         buffer++;
769                                         target+=m_event_size;
770                                 }
771                         }
772                         break;
773                 case Port::E_Float:
774                         {
775                                 const float multiplier = (float)(0x7FFFFF);
776                                 float *buffer=(float *)(p->getBufferAddress());
777
778                                 assert(nevents + offset <= p->getBufferSize());
779
780                                 buffer+=offset;
781
782                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
783                                         unsigned int v = (int)(*buffer * multiplier);
784                                         *target = (v >> 16) & 0xff;
785                                         *(target+1) = (v >> 8) & 0xff;
786                                         *(target+2) = v & 0xff;
787
788                                         buffer++;
789                                         target+=m_event_size;
790                                 }
791                         }
792                         break;
793         }
794
795         return 0;
796 }
797
798 int MotuTransmitStreamProcessor::encodeSilencePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,
799                        unsigned int offset, unsigned int nevents) {
800         unsigned int j=0;
801         unsigned char *target = (unsigned char *)data + p->getPosition();
802
803         switch (p->getDataType()) {
804         default:
805         case Port::E_Int24:
806         case Port::E_Float:
807                 for (j = 0; j < nevents; j++) {
808                         *target = *(target+1) = *(target+2) = 0;
809                         target += m_event_size;
810                 }
811                 break;
812         }
813
814         return 0;
815 }
816
817 bool MotuTransmitStreamProcessor::preparedForStop() {
818
819         // If the stream is disabled or isn't running there's no need to
820         // wait since the MOTU *should* still be in a "zero data" state.
821         //
822         // If the m_streaming_active flag is 0 it indicates that the
823         // transmit callback hasn't been called since a closedown was
824         // requested when this function was last called.  This effectively
825         // signifies that the streaming thread has been exitted due to an
826         // xrun in either the receive or transmit handlers.  In this case
827         // there's no point in waiting for the closedown count to hit zero
828         // because it never will; the zero data will never get to the MOTU.
829         // It's best to allow an immediate stop and let the xrun handler
830         // proceed as best it can.
831         //
832         // The ability to detect the lack of streaming also prevents the
833         // "wait for stop" in the stream processor manager's stop() method
834         // from hitting its timeout which in turn seems to increase the
835         // probability of a successful recovery.
836         if (m_disabled || !isRunning() || !m_streaming_active)
837                 return true;
838
839         if (m_closedown_count < 0) {
840                 // No closedown has been initiated, so start one now.  Set
841                 // the closedown count to the number of zero packets which
842                 // will be sent to the MOTU before closing off the iso
843                 // streams.  FIXME: 128 packets (each containing 8 frames at
844                 // 48 kHz) is the experimentally-determined figure for 48
845                 // kHz with a period size of 1024.  It seems that at least
846                 // one period of zero samples need to be sent to allow for
847                 // inter-thread communication occuring on period boundaries.
848                 // This needs to be confirmed for other rates and period
849                 // sizes.
850                 signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32);
851                 m_closedown_count = m_period / n_events;
852
853                 // Set up a test to confirm that streaming is still active.
854                 // If the streaming function hasn't been called by the next
855                 // iteration through this function there's no point in
856                 // continuing since it means the zero data will never get to
857                 // the MOTU.
858                 m_streaming_active = 0;
859                 return false;
860         }
861
862         // We are "go" for closedown once all requested zero packets
863         // (initiated by a previous call to this function) have been sent to
864         // the MOTU.
865         return m_closedown_count == 0;
866 }
867
868 /* --------------------- RECEIVE ----------------------- */
869
870 MotuReceiveStreamProcessor::MotuReceiveStreamProcessor(int port, int framerate,
871         unsigned int event_size)
872     : ReceiveStreamProcessor(port, framerate), m_event_size(event_size),
873         m_last_cycle_ofs(-1), m_next_cycle(-1) {
874
875         // Set up the Delay-locked-loop to track audio frequency relative
876         // to the cycle timer.  The seed value is the "ideal" value.
877         m_ticks_per_frame = 24576000.0/framerate;
878 }
879
880 MotuReceiveStreamProcessor::~MotuReceiveStreamProcessor() {
881         freebob_ringbuffer_free(m_event_buffer);
882         free(m_tmp_event_buffer);
883 }
884
885 bool MotuReceiveStreamProcessor::init() {
886
887     // call the parent init
888     // this has to be done before allocating the buffers,
889     // because this sets the buffersizes from the processormanager
890     if(!ReceiveStreamProcessor::init()) {
891         debugFatal("Could not do base class init (%d)\n",this);
892         return false;
893     }
894
895     return true;
896 }
897
898 enum raw1394_iso_disposition
899 MotuReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,
900                   unsigned char channel, unsigned char tag, unsigned char sy,
901                   unsigned int cycle, unsigned int dropped) {
902    
903     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
904     signed int have_lost_cycles = 0;
905
906     // Detect missed receive cycles
907     // FIXME: it would be nice to advance the rx buffer by the amount of
908     // frames missed.  However, since the MOTU transmits more frames
909     // per cycle than the average and "catches up" with period emty
910     // cycles it's not trivial to work out precisely how many frames
911     // were missed.  Ultimately we need to do so if sync is to be
912     // maintained across a transient receive failure.
913     if (m_next_cycle < 0)
914         m_next_cycle = cycle;
915     if ((signed)cycle != m_next_cycle) {
916         debugOutput(DEBUG_LEVEL_VERBOSE, "lost rx cycles; received %d, expected %d\n",
917             cycle, m_next_cycle);
918         m_next_cycle = cycle;
919         have_lost_cycles = 1;
920     }
921     if (++m_next_cycle >= 8000)
922         m_next_cycle -= 8000;
923
924     // If the packet length is 8 bytes (ie: just a CIP-like header) there is
925     // no isodata.
926     if (length > 8) {
927         // The iso data blocks from the MOTUs comprise a CIP-like header
928         // followed by a number of events (8 for 1x rates, 16 for 2x rates,
929         // 32 for 4x rates).
930         quadlet_t *quadlet = (quadlet_t *)data;
931         unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size
932         unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits
933         unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes
934         unsigned int n_events = (length-8) / event_length;
935
936         // Don't even attempt to process a packet if it isn't what we expect
937         // from a MOTU
938         if (tag!=1 || fdf_size!=32) {
939                 return RAW1394_ISO_OK;
940         }
941
942         // Signal that we're running
943         if (n_events) m_running=true;
944
945         /* Send actual ticks-per-frame values (as deduced by the incoming
946          * SPHs) to the DLL for averaging.  Doing this here means the DLL
947          * should acquire a reasonable estimation of the ticks per frame
948          * even while the stream is formally disabled.  This in turn means
949          * the transmit stream should have access to a very realistic
950          * estimate by the time it is enabled.  The major disadvantage
951          * is a small increase in the overheads of this function compared
952          * to what would be the case if this was delayed by pushing it into
953          * the decode functions.
954          */
955         unsigned int ev;
956         signed int sph_ofs;
957
958         /* If this is the first block received or we have lost cycles,
959          * initialise the m_last_cycle_ofs to a value which won't cause the
960          * DLL to become polluted with an inappropriate ticks-per-frame
961          * estimate.
962          */
963         if (m_last_cycle_ofs<0 || have_lost_cycles) {
964                 sph_ofs = ntohl(*(quadlet_t *)(data+8)) & 0xfff;
965                 m_last_cycle_ofs = sph_ofs-(int)(m_ticks_per_frame);
966         }
967         for (ev=0; ev<n_events; ev++) {
968                 sph_ofs = ntohl(*(quadlet_t *)(data+8+ev*m_event_size)) & 0xfff;
969                 signed int sph_diff = (sph_ofs - m_last_cycle_ofs);
970                 // Handle wraparound of the cycle offset
971                 if (sph_diff < 0)
972                         sph_diff += 3072;
973                 float err = sph_diff - m_ticks_per_frame;
974                 // FIXME: originally we used a value of 0.0005 for the coefficient
975                 // which mirrored the value used in
976                 // AmdtpReceiveStreamProcessor::putPacket() for a similar purpose.
977                 // However, tests showed that this introduced discontinuities in
978                 // the output audio signal, so an alternative value was sought.
979                 // Further tests are needed, but a value of 0.015 seems to work
980                 // well, at least at a sample rate of 48 kHz.
981                 m_ticks_per_frame += 0.015*err;
982                 m_last_cycle_ofs = sph_ofs;
983         }
984
985         // Don't process the stream when it is not enabled.
986         if (m_disabled) {
987                 return RAW1394_ISO_OK;
988         }
989        
990         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n");
991
992         // Add the data payload (events) to the ringbuffer.  We'll just copy
993         // everything including the 4 byte timestamp at the start of each
994         // event (that is, everything except the CIP-like header).  The
995         // demultiplexer can deal with the complexities such as the channel
996         // 24-bit data.
997         unsigned int write_size = length-8;
998         if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size) {
999                 debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",
1000                         cycle, m_framecounter, m_handler->getPacketCount());
1001                 m_xruns++;
1002
1003                 retval=RAW1394_ISO_DEFER;
1004         } else {
1005                 retval=RAW1394_ISO_OK;
1006                 // Process all ports that should be handled on a per-packet basis
1007                 // This is MIDI for AMDTP (due to the need of DBC)
1008                 int dbc = get_bits(ntohl(quadlet[0]), 8, 8);  // Low byte of CIP quadlet 0
1009                 if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) {
1010                         debugWarning("Problem decoding Packet Ports\n");
1011                         retval=RAW1394_ISO_DEFER;
1012                 }
1013                 // time stamp processing can be done here
1014         }
1015
1016         // update the frame counter
1017         incrementFrameCounter(n_events);
1018         // keep this at the end, because otherwise the raw1394_loop_iterate functions inner loop
1019         // keeps requesting packets without going to the xmit handler, leading to xmit starvation
1020         if(m_framecounter>(signed int)m_period) {
1021                 retval=RAW1394_ISO_DEFER;
1022         }
1023        
1024     } else { // no events in packet
1025         // discard packet
1026         // can be important for sync though
1027     }
1028    
1029     return retval;
1030 }
1031
1032 bool MotuReceiveStreamProcessor::isOnePeriodReady() {
1033      // TODO: this is the way you can implement sync
1034      //       only when this returns true, one period will be
1035      //       transferred to the audio api side.
1036      //       you can delay this moment as long as you
1037      //       want (provided that there is enough buffer space)
1038      
1039      // this implementation just waits until there is one period of samples
1040      // received into the buffer
1041     if(m_framecounter > (signed int)m_period) {
1042         return true;
1043     }
1044     return false;
1045 }
1046
1047 void MotuReceiveStreamProcessor::setVerboseLevel(int l) {
1048         setDebugLevel(l);
1049         ReceiveStreamProcessor::setVerboseLevel(l);
1050
1051 }
1052
1053
1054 bool MotuReceiveStreamProcessor::reset() {
1055
1056         debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
1057
1058         // reset the event buffer, discard all content
1059         freebob_ringbuffer_reset(m_event_buffer);
1060
1061         // reset all non-device specific stuff
1062         // i.e. the iso stream and the associated ports
1063         if(!ReceiveStreamProcessor::reset()) {
1064                 debugFatal("Could not do base class reset\n");
1065                 return false;
1066         }
1067        
1068         return true;
1069 }
1070
1071 bool MotuReceiveStreamProcessor::prepare() {
1072
1073         // prepare all non-device specific stuff
1074         // i.e. the iso stream and the associated ports
1075         if(!ReceiveStreamProcessor::prepare()) {
1076                 debugFatal("Could not prepare base class\n");
1077                 return false;
1078         }
1079
1080         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
1081
1082         m_PeriodStat.setName("RCV PERIOD");
1083         m_PacketStat.setName("RCV PACKET");
1084         m_WakeupStat.setName("RCV WAKEUP");
1085
1086     // setup any specific stuff here
1087
1088         debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size);
1089    
1090         // allocate the event buffer
1091         unsigned int ringbuffer_size_frames=m_nb_buffers * m_period;
1092
1093         if( !(m_event_buffer=freebob_ringbuffer_create(
1094                         m_event_size * ringbuffer_size_frames))) {
1095                 debugFatal("Could not allocate memory event ringbuffer");
1096                 return false;
1097         }
1098
1099         // allocate the temporary event buffer
1100         if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) {
1101                 debugFatal("Could not allocate temporary event buffer");
1102                 freebob_ringbuffer_free(m_event_buffer);
1103                 return false;
1104         }
1105
1106         // set the parameters of ports we can:
1107         // we want the audio ports to be period buffered,
1108         // and the midi ports to be packet buffered
1109         for ( PortVectorIterator it = m_Ports.begin();
1110                   it != m_Ports.end();
1111                   ++it )
1112         {
1113                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
1114                
1115                 if(!(*it)->setBufferSize(m_period)) {
1116                         debugFatal("Could not set buffer size to %d\n",m_period);
1117                         return false;
1118                 }
1119
1120                 switch ((*it)->getPortType()) {
1121                         case Port::E_Audio:
1122                                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
1123                                         debugFatal("Could not set signal type to PeriodSignalling");
1124                                         return false;
1125                                 }
1126                                 break;
1127                         case Port::E_Midi:
1128                                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
1129                                         debugFatal("Could not set signal type to PacketSignalling");
1130                                         return false;
1131                                 }
1132                                 break;
1133                         case Port::E_Control:
1134                                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
1135                                         debugFatal("Could not set signal type to PeriodSignalling");
1136                                         return false;
1137                                 }
1138                                 break;
1139                         default:
1140                                 debugWarning("Unsupported port type specified\n");
1141                                 break;
1142                 }
1143
1144         }
1145
1146         // The API specific settings of the ports are already set before
1147         // this routine is called, therefore we can init&prepare the ports
1148         if(!initPorts()) {
1149                 debugFatal("Could not initialize ports!\n");
1150                 return false;
1151         }
1152
1153         if(!preparePorts()) {
1154                 debugFatal("Could not initialize ports!\n");
1155                 return false;
1156         }
1157        
1158         return true;
1159
1160 }
1161
1162 bool MotuReceiveStreamProcessor::transfer() {
1163
1164     // the same idea as the transmit processor
1165    
1166         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
1167        
1168 /* another naive section:       
1169         unsigned int read_size=m_period*m_event_size;
1170         char *dummybuffer=(char *)calloc(m_period,m_event_size);
1171         if (freebob_ringbuffer_read(m_event_buffer,(char *)(dummybuffer),read_size) < read_size) {
1172                 debugWarning("Could not read from event buffer\n");
1173         }
1174
1175         receiveBlock(dummybuffer, m_period, 0);
1176
1177         free(dummybuffer);
1178 */
1179         int xrun;
1180         unsigned int offset=0;
1181        
1182         freebob_ringbuffer_data_t vec[2];
1183         // We received one period of frames from each channel.
1184         // This is period_size*m_event_size bytes.
1185         unsigned int bytes2read = m_period * m_event_size;
1186
1187         /* Read events2read bytes from the ringbuffer.
1188         *  First see if it can be done in one read.  If so, ok.
1189         *  Otherwise read up to a multiple of events directly from the buffer
1190         *  then do the buffer wrap around using ringbuffer_read
1191         *  then read the remaining data directly from the buffer in a third pass
1192         *  Make sure that we cannot end up on a non-event aligned position!
1193         */
1194         while(bytes2read>0) {
1195                 unsigned int framesread=(m_period*m_event_size-bytes2read)/m_event_size;
1196                 offset=framesread;
1197                
1198                 int bytesread=0;
1199
1200                 freebob_ringbuffer_get_read_vector(m_event_buffer, vec);
1201                        
1202                 if(vec[0].len==0) { // this indicates an empty event buffer
1203                         debugError("RCV: Event buffer underrun in processor %p\n",this);
1204                         break;
1205                 }
1206                        
1207                 /* if we don't take care we will get stuck in an infinite loop
1208                 * because we align to an event boundary later
1209                 * the remaining nb of bytes in one read operation can be smaller than one event
1210                 * this can happen because the ringbuffer size is always a power of 2
1211                 */
1212                 if(vec[0].len<m_event_size) {
1213                         // use the ringbuffer function to read one event
1214                         // the read function handles wrap around
1215                         freebob_ringbuffer_read(m_event_buffer,m_tmp_event_buffer,m_event_size);
1216
1217                         xrun = receiveBlock(m_tmp_event_buffer, 1, offset);
1218                                
1219                         if(xrun<0) {
1220                                 // xrun detected
1221                                 debugError("RCV: Frame buffer overrun in processor %p\n",this);
1222                                 break;
1223                         }
1224                                
1225                         // We advanced one m_event_size
1226                         bytes2read-=m_event_size;
1227                                
1228                 } else { //
1229                        
1230                         if(bytes2read>vec[0].len) {
1231                                         // align to an event boundary
1232                                 bytesread=vec[0].len-(vec[0].len%m_event_size);
1233                         } else {
1234                                 bytesread=bytes2read;
1235                         }
1236                                
1237                         xrun = receiveBlock(vec[0].buf, bytesread/m_event_size, offset);
1238                                
1239                         if(xrun<0) {
1240                                 // xrun detected
1241                                 debugError("RCV: Frame buffer overrun in processor %p\n",this);
1242                                 break;
1243                         }
1244
1245                         freebob_ringbuffer_read_advance(m_event_buffer, bytesread);
1246                         bytes2read -= bytesread;
1247                 }
1248                        
1249                 // the bytes2read should always be event aligned
1250                 assert(bytes2read%m_event_size==0);
1251         }
1252
1253         return true;
1254 }
1255
1256 /**
1257  * \brief write received events to the port ringbuffers.
1258  */
1259 int MotuReceiveStreamProcessor::receiveBlock(char *data,
1260                                            unsigned int nevents, unsigned int offset)
1261 {
1262         int problem=0;
1263         for ( PortVectorIterator it = m_PeriodPorts.begin();
1264           it != m_PeriodPorts.end();
1265           ++it ) {
1266                 if((*it)->isDisabled()) {continue;};
1267
1268                 //FIXME: make this into a static_cast when not DEBUG?
1269                 Port *port=dynamic_cast<Port *>(*it);
1270                
1271                 switch(port->getPortType()) {
1272                
1273                 case Port::E_Audio:
1274                         if(decodeMBLAEventsToPort(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
1275                                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str());
1276                                 problem=1;
1277                         }
1278                         break;
1279                 // midi is a packet based port, don't process
1280                 //      case MotuPortInfo::E_Midi:
1281                 //              break;
1282
1283                 default: // ignore
1284                         break;
1285                 }
1286         }
1287         return problem;
1288 }
1289
1290 /**
1291  * @brief decode a packet for the packet-based ports
1292  *
1293  * @param data Packet data
1294  * @param nevents number of events in data (including events of other ports & port types)
1295  * @param dbc DataBlockCount value for this packet
1296  * @return true if all successfull
1297  */
1298 bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
1299 {
1300         bool ok=true;
1301        
1302         quadlet_t *target_event=NULL;
1303         int j;
1304        
1305         for ( PortVectorIterator it = m_PacketPorts.begin();
1306           it != m_PacketPorts.end();
1307           ++it ) {
1308
1309 #ifdef DEBUG
1310                 MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it);
1311                 assert(pinfo); // this should not fail!!
1312
1313                 // the only packet type of events for AMDTP is MIDI in mbla
1314 //              assert(pinfo->getFormat()==MotuPortInfo::E_Midi);
1315 #endif
1316                 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);
1317                
1318
1319         // do decoding here
1320
1321         }
1322        
1323         return ok;
1324 }
1325
1326 signed int MotuReceiveStreamProcessor::decodeMBLAEventsToPort(MotuAudioPort *p,
1327                 quadlet_t *data, unsigned int offset, unsigned int nevents)
1328 {
1329         unsigned int j=0;
1330
1331         // Use char here since a port's source address won't necessarily be
1332         // aligned; use of an unaligned quadlet_t may cause issues on
1333         // certain architectures.  Besides, the source (data coming directly
1334         // from the MOTU) isn't structured in quadlets anyway; it mainly
1335         // consists of packed 24-bit integers.
1336
1337         unsigned char *src_data;
1338         src_data = (unsigned char *)data + p->getPosition();
1339
1340         switch(p->getDataType()) {
1341                 default:
1342                 case Port::E_Int24:
1343                         {
1344                                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
1345
1346                                 assert(nevents + offset <= p->getBufferSize());
1347
1348                                 // Offset is in frames, but each port is only a single
1349                                 // channel, so the number of frames is the same as the
1350                                 // number of quadlets to offset (assuming the port buffer
1351                                 // uses one quadlet per sample, which is the case currently).
1352                                 buffer+=offset;
1353
1354                                 for(j = 0; j < nevents; j += 1) { // Decode nsamples
1355                                         *buffer = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
1356                                         // Sign-extend highest bit of 24-bit int.
1357                                         // FIXME: this isn't strictly needed since E_Int24 is a 24-bit,
1358                                         // but doing so shouldn't break anything and makes the data
1359                                         // easier to deal with during debugging.
1360                                         if (*src_data & 0x80)
1361                                                 *buffer |= 0xff000000;
1362
1363                                         buffer++;
1364                                         src_data+=m_event_size;
1365                                 }
1366                         }
1367                         break;
1368                 case Port::E_Float:
1369                         {
1370                                 const float multiplier = 1.0f / (float)(0x7FFFFF);
1371                                 float *buffer=(float *)(p->getBufferAddress());
1372
1373                                 assert(nevents + offset <= p->getBufferSize());
1374
1375                                 buffer+=offset;
1376
1377                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
1378        
1379                                         unsigned int v = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
1380
1381                                         // sign-extend highest bit of 24-bit int
1382                                         int tmp = (int)(v << 8) / 256;
1383                
1384                                         *buffer = tmp * multiplier;
1385                                
1386                                         buffer++;
1387                                         src_data+=m_event_size;
1388                                 }
1389                         }
1390                         break;
1391         }
1392
1393         return 0;
1394 }
1395
1396 signed int MotuReceiveStreamProcessor::setEventSize(unsigned int size) {
1397         m_event_size = size;
1398         return 0;
1399 }
1400
1401 unsigned int MotuReceiveStreamProcessor::getEventSize(void) {
1402 //
1403 // Return the size of a single event sent by the MOTU as part of an iso
1404 // data packet in bytes.
1405 //
1406         return m_event_size;
1407 }
1408                
1409 } // end of namespace FreebobStreaming
Note: See TracBrowser for help on using the browser.