root/branches/streaming-rework/src/libstreaming/AmdtpStreamProcessor.cpp

Revision 383, 63.1 kB (checked in by pieterpalmers, 16 years ago)

mostly whitespace fixes

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  *
11  *   This program is free software {} you can redistribute it and/or modify
12  *   it under the terms of the GNU General Public License as published by
13  *   the Free Software Foundation {} either version 2 of the License, or
14  *   (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program {} if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  *
26  *
27  */
28
29 #include "AmdtpStreamProcessor.h"
30 #include "Port.h"
31 #include "AmdtpPort.h"
32
33 #include "cyclecounter.h"
34
35 #include <netinet/in.h>
36 #include <assert.h>
37
38 #define RECEIVE_PROCESSING_DELAY_IN_SAMPLES 100
39 #define RECEIVE_DLL_INTEGRATION_COEFFICIENT 0.015
40
41 #define RECEIVE_PROCESSING_DELAY (TICKS_PER_SECOND * 2/1000)
42
43 // in ticks
44 #define TRANSMIT_TRANSFER_DELAY 10000
45
46 //#define DO_SYT_SYNC
47
48 namespace FreebobStreaming {
49
50 IMPL_DEBUG_MODULE( AmdtpTransmitStreamProcessor, AmdtpTransmitStreamProcessor, DEBUG_LEVEL_NORMAL );
51 IMPL_DEBUG_MODULE( AmdtpReceiveStreamProcessor, AmdtpReceiveStreamProcessor, DEBUG_LEVEL_NORMAL );
52
53
54 /* transmit */
55 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(int port, int framerate, int dimension)
56         : TransmitStreamProcessor(port, framerate), m_dimension(dimension)
57         , m_last_timestamp(0), m_dbc(0), m_ringbuffer_size_frames(0)
58         {
59
60
61 }
62
63 AmdtpTransmitStreamProcessor::~AmdtpTransmitStreamProcessor() {
64         freebob_ringbuffer_free(m_event_buffer);
65         free(m_cluster_buffer);
66 }
67
68 /**
69  * @return
70  */
71 bool AmdtpTransmitStreamProcessor::init() {
72
73         debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing (%p)...\n");
74         // call the parent init
75         // this has to be done before allocating the buffers,
76         // because this sets the buffersizes from the processormanager
77         if(!TransmitStreamProcessor::init()) {
78                 debugFatal("Could not do base class init (%p)\n",this);
79                 return false;
80         }
81        
82
83         return true;
84 }
85
86 void AmdtpTransmitStreamProcessor::setVerboseLevel(int l) {
87         setDebugLevel(l);
88         TransmitStreamProcessor::setVerboseLevel(l);
89 }
90
91 enum raw1394_iso_disposition
92 AmdtpTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length,
93                       unsigned char *tag, unsigned char *sy,
94                       int cycle, unsigned int dropped, unsigned int max_length) {
95    
96     struct iec61883_packet *packet = (struct iec61883_packet *) data;
97     unsigned int nevents=0;
98    
99     packet->eoh0 = 0;
100    
101 #ifdef DEBUG
102     if(dropped>0) {
103         debugWarning("Dropped %d packets on cycle %d\n",dropped, cycle);
104     }
105 #endif
106    
107     /* Our node ID can change after a bus reset, so it is best to fetch
108      * our node ID for each packet. */
109     packet->sid = getNodeId() & 0x3f;
110
111     packet->dbs = m_dimension;
112     packet->fn = 0;
113     packet->qpc = 0;
114     packet->sph = 0;
115     packet->reserved = 0;
116     packet->dbc = m_dbc;
117     packet->eoh1 = 2;
118     packet->fmt = IEC61883_FMT_AMDTP;
119
120     // signal that we are running (a transmit stream is always 'runnable')
121     m_running=true;
122    
123     // don't process the stream when it is not enabled.
124     // however, we do have to generate (semi) valid packets
125     // that means that we'll send NODATA packets FIXME: check!!
126     if(m_disabled) {
127         // no-data packets have syt=0xFFFF
128         // and have the usual amount of events as dummy data
129         packet->fdf = IEC61883_FDF_NODATA;
130         packet->syt = 0xffff;
131        
132         // the dbc is incremented even with no data packets
133         m_dbc += m_syt_interval;
134
135         *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t);
136         *tag = IEC61883_TAG_WITH_CIP;
137         *sy = 0;
138
139         return RAW1394_ISO_DEFER;
140     }
141    
142     packet->fdf = m_fdf;
143        
144 //     assert(m_handler->getDroppedCount()<5);
145        
146 //     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n");
147        
148         // construct the packet cip
149         // NOTE: maybe a little outdated
150         // FIXME: this should be done differently:
151         // first we should determine the timestamp of the first sample in this block
152         // this can be done by reading the rate of the compagnion receiver
153         // this rate will give us the ticks per sample used by the device
154         // then we should take the previous timestamp, and add m_syt_interval * ticks_per_sample
155         // to this timestamp (only if we are sending events). This gives us the timestamp
156         // of the first sample in this packet.
157         // we should define a transfer delay and add it to this timestamp and then send it to
158         // the device.
159        
160         // NOTE: this will even work when we're only transmitting (no receive stream):
161         //       the ticks_per_sample value is initialized by the receive streamprocessor
162         //       to the nominal value. We will then transmit at our own pace, being at nominal
163         //       rate compared to the cycle counter.
164
165     // NOTE: this scheme might even work when sync'ing on the sync streams of the device
166     //       they are AMDTP streams with SYT timestamps, therefore a decent estimate of
167     //       ticks_per_frame can be found, and we are synced when using it.
168        
169 //      <<compile error here>>
170        
171     // FIXME: if m_last_bufferfill > 0
172     float ticks_per_frame=syncmaster->getTicksPerFrame();
173
174     // m_last_timestamp is the moment upon which the last 'period signal' 
175     // should have been given (note: should have been because
176     // the timestamp is derrived from the incoming packets,
177     // not from the moment the signal was actually given)
178    
179     // at a period boundary, we expect m_ringbuffer_size_frames frames to
180     // be in the buffers. 'right after' the transfer(), all of these
181     // frames should be in the xmit buffers (if transfer() finishes
182     // before new packets are received)
183     // therefore the last sample of the xmit buffer lies at
184     // T1 = timestamp + (m_ringbuffer_size_frames) * ticks_per_frame
185    
186     // in reality however life is multithreaded, and we don't know
187     // exactly how many samples there are in the buffer. but we know
188     // how many there should be, so we say that the last frame put
189     // into the buffer (by transfer) has the timestamp T1
190    
191     // this means that the current sample has timestamp
192     // T2 = T1 - ticks_per_frame * (nb_frames_in_buffer)
193     //    = T1 - ticks_per_frame * (m_ringbuffer_size_frames-m_framecounter)
194     //    = timestamp + ticks_per_frame *
195     //      (m_ringbuffer_size_frames-m_ringbuffer_size_frames+m_framecounter)
196     //    = timestamp + ticks_per_frame * m_framecounter
197    
198     int T2 = m_last_timestamp + ticks_per_frame*m_framecounter;
199    
200     // we then need to add the transfer delay for the receiving
201     // device to this time to determine the xmit timestamp
202     // TSTAMP = T2 + TRANSFER_DELAY
203    
204     // we should determine when to 'queue' this sample to
205     // the ISO xmit layer, based upon the cycle parameter
206     // we can define the ideal time at which to send the sample as
207     // TSEND = TSTAMP - TRANSFER_DELAY
208     // being T2
209     int TSEND = T2;
210    
211     // the xmit timestamp should then be the TSEND + TRANSMIT_TRANSFER_DELAY
212     // note that in this setup, TRANSMIT_TRANSFER_DELAY has to incorporate the
213     // iso buffering
214     int timestamp = TSEND + TRANSMIT_TRANSFER_DELAY;
215    
216     // if we take a look at TSEND we can determine if we are to send
217     // the sample or not:
218     // if
219     // CYCLES(TSEND) < cycle
220     // then the time at which to send the packet has passed (note: wraparound!)
221     // we should send the sample
222     // if it hasn't passed, we should send an empty packet
223     //
224     // this should automatically catch up
225    
226     // FIXME: wraparound!
227     int cycle_wo_wraparound=cycle;
228    
229     int TSEND_cycle_wo_wraparound = TICKS_TO_CYCLES(TSEND);
230    
231     // arbitrary, should be replaced by a better wraparound
232     // detection
233    
234     // if cycles wraps around, and TSEND_cyles doesn't,
235     // we need to make sure that we compare the right things
236     // i.e. unwrap the cycle parameter
237     // if both wrap, this can't be true
238     if (cycle_wo_wraparound - TSEND_cycle_wo_wraparound < -4000) {
239         cycle_wo_wraparound += 8000;
240        
241          debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"wraparound on cycle detected: %d %d %d\n",
242             cycle, cycle_wo_wraparound,
243             cycle - TSEND_cycle_wo_wraparound);
244     }
245    
246     // if TSEND_cycle wraps around and cycle doesn't,
247     // TSEND_cycle suddenly becomes a lot smaller than cycle
248     if (TSEND_cycle_wo_wraparound - cycle_wo_wraparound < -4000) {
249         TSEND_cycle_wo_wraparound += 8000;
250        
251          debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"wraparound on TSEND detected: %d %d %d\n",
252             TICKS_TO_CYCLES(TSEND), TSEND_cycle_wo_wraparound,
253             TSEND_cycle_wo_wraparound - cycle_wo_wraparound);
254     }
255  
256     if (TSEND_cycle_wo_wraparound < cycle_wo_wraparound) {
257         nevents=m_syt_interval;
258         m_dbc += m_syt_interval;
259
260     } else { // no-data
261  
262            // no-data packets have syt=0xFFFF
263            // and have the usual amount of events as dummy data
264         packet->fdf = IEC61883_FDF_NODATA;
265         packet->syt = 0xffff;
266        
267         // the dbc is incremented even with no data packets
268         m_dbc += m_syt_interval;
269        
270                 *length = 2*sizeof(quadlet_t) + m_syt_interval * m_dimension * sizeof(quadlet_t);
271                 *tag = IEC61883_TAG_WITH_CIP;
272                 *sy = 0;
273
274 //         if(packet->dbs) {
275 //             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
276 //                 "XMT %04d: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",
277 //                 cycle, m_channel, packet->fdf,
278 //                 packet->syt,
279 //                 packet->dbs,
280 //                 packet->dbc,
281 //                 packet->fmt,
282 //                 *length,
283 //                 ((*length / sizeof (quadlet_t)) - 2)/packet->dbs);
284 //         }
285        
286                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Sending empty packet on cycle %d\n", cycle);
287        
288         // FIXME: this is to prevent libraw to do loop over too
289         //        much packets at once (overflowing the receive side)
290         //        but putting it here is a little arbitrary
291        
292    
293                 return RAW1394_ISO_DEFER;
294     }
295    
296
297 //     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Now=%4d/%8d, Tstamp=%8d, DT=%8d, T2=%8d, T3=%8d, last TS=%d, BF=%d\n",
298 //         cycle,(cycle*3072),
299 //         timestamp,
300 //         timestamp-(cycle*3072),
301 //         T2,T3,
302 //         m_last_timestamp,
303 //         buffer_fill);
304    
305         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
306
307         unsigned int read_size=nevents*sizeof(quadlet_t)*m_dimension;
308
309         if ((freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size)) <
310                                 read_size)
311         {
312         /* there is no more data in the ringbuffer */
313        
314         debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",
315                  cycle, m_framecounter, m_handler->getPacketCount());
316        
317         // signal underrun
318         m_xruns++;
319
320         retval=RAW1394_ISO_DEFER;
321         *length=0;
322         nevents=0;
323
324
325     } else {
326         retval=RAW1394_ISO_OK;
327         *length = read_size + 8;
328        
329         // process all ports that should be handled on a per-packet base
330         // this is MIDI for AMDTP (due to the need of DBC)
331         if (!encodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) {
332             debugWarning("Problem encoding Packet Ports\n");
333         }
334        
335         // we can forget the seconds for the cycle counter
336         // because we are masking with 0xFFFF
337        
338         unsigned int timestamp_SYT = (TICKS_TO_CYCLES(timestamp) << 12)
339                                      | TICKS_TO_OFFSET(timestamp);
340        
341         packet->syt = ntohs(timestamp_SYT & 0xffff);
342        
343 //         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"XMIT %d EVENTS, SYT %04X for cycle %2d: %08d (%2u cycles + %04u ticks)\n",
344 //           nevents, timestamp_SYT & 0xFFFF, cycle, timestamp_SYT
345 //           CYCLE_COUNTER_GET_CYCLES(timestamp_SYT),
346 //           CYCLE_COUNTER_GET_OFFSET(timestamp_SYT)
347 //           );
348     }
349    
350     *tag = IEC61883_TAG_WITH_CIP;
351     *sy = 0;
352    
353     // update the frame counter
354     incrementFrameCounter(nevents);
355    
356 /*    if(m_framecounter>m_period) {
357        retval=RAW1394_ISO_DEFER;
358     }*/
359    
360 #ifdef DEBUG
361 //     if(packet->dbs) {
362 //         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
363 //             "XMT %04d: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",
364 //             cycle, m_channel, packet->fdf,
365 //             packet->syt,
366 //             packet->dbs,
367 //             packet->dbc,
368 //             packet->fmt,
369 //             *length,
370 //             ((*length / sizeof (quadlet_t)) - 2)/packet->dbs);
371 //     }
372 #endif
373
374     return retval;
375
376 }
377
378 void AmdtpTransmitStreamProcessor::decrementFrameCounter() {
379     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "decrement frame counter...\n");
380
381 #ifdef DEBUG
382     int xmit_bufferspace=freebob_ringbuffer_read_space(m_event_buffer)/m_dimension/4;
383     int recv_bufferspace=freebob_ringbuffer_read_space(syncmaster->m_event_buffer)/syncmaster->m_dimension/4;
384    
385     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"XMT: %5d | RCV: %5d | DIFF: %5d | SUM: %5d \n", xmit_bufferspace, recv_bufferspace, xmit_bufferspace - recv_bufferspace, xmit_bufferspace + recv_bufferspace);
386 #endif
387
388     // update the timestamp
389    
390     m_last_timestamp=syncmaster->getPeriodTimeStamp();
391    
392     StreamProcessor::decrementFrameCounter();
393 }
394
395 void AmdtpTransmitStreamProcessor::incrementFrameCounter(int nbframes) {
396     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "increment frame counter by %d...\n", nbframes);
397    
398     StreamProcessor::incrementFrameCounter(nbframes);
399 }
400
401 bool AmdtpTransmitStreamProcessor::isOnePeriodReady()
402 {
403     return true;
404     //return (m_framecounter > m_period);
405 }
406
407 bool AmdtpTransmitStreamProcessor::prefill() {
408
409     if(!transferSilence(m_ringbuffer_size_frames)) {
410         debugFatal("Could not prefill transmit stream\n");
411         return false;
412     }
413
414 /*    int i=m_nb_buffers;
415     while(i--) {
416         if(!transferSilence(m_period)) {
417             debugFatal("Could not prefill transmit stream\n");
418             return false;
419         }
420     }
421    
422     // and we should also provide enough prefill for the
423     // SYT processing delay
424     if(!transferSilence(RECEIVE_PROCESSING_DELAY_IN_SAMPLES)) {
425         debugFatal("Could not prefill transmit stream (2)\n");
426         return false;
427     }
428 */   
429     // the framecounter should be pulled back to
430     // make sure the ISO buffering is used
431     // we are using 1 period of iso buffering
432 //     m_framecounter=-m_period;
433    
434     // should this also be pre-buffered?
435     //m_framecounter=-(m_framerate * RECEIVE_PROCESSING_DELAY)/TICKS_PER_SECOND;
436    
437     return true;
438    
439 }
440
441 bool AmdtpTransmitStreamProcessor::reset() {
442
443     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
444
445     // reset the event buffer, discard all content
446     freebob_ringbuffer_reset(m_event_buffer);
447    
448     // reset the statistics
449     m_PeriodStat.reset();
450     m_PacketStat.reset();
451     m_WakeupStat.reset();
452    
453     // reset all non-device specific stuff
454     // i.e. the iso stream and the associated ports
455     if(!TransmitStreamProcessor::reset()) {
456         debugFatal("Could not do base class reset\n");
457         return false;
458     }
459    
460     // we should prefill the event buffer
461     if (!prefill()) {
462         debugFatal("Could not prefill buffers\n");
463         return false;   
464     }
465    
466     return true;
467 }
468
469 bool AmdtpTransmitStreamProcessor::prepare() {
470     m_PeriodStat.setName("XMT PERIOD");
471     m_PacketStat.setName("XMT PACKET");
472     m_WakeupStat.setName("XMT WAKEUP");
473
474     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
475    
476     // prepare all non-device specific stuff
477     // i.e. the iso stream and the associated ports
478     if(!TransmitStreamProcessor::prepare()) {
479         debugFatal("Could not prepare base class\n");
480         return false;
481     }
482    
483     switch (m_framerate) {
484     case 32000:
485         m_syt_interval = 8;
486         m_fdf = IEC61883_FDF_SFC_32KHZ;
487         break;
488     case 44100:
489         m_syt_interval = 8;
490         m_fdf = IEC61883_FDF_SFC_44K1HZ;
491         break;
492     default:
493     case 48000:
494         m_syt_interval = 8;
495         m_fdf = IEC61883_FDF_SFC_48KHZ;
496         break;
497     case 88200:
498         m_syt_interval = 16;
499         m_fdf = IEC61883_FDF_SFC_88K2HZ;
500         break;
501     case 96000:
502         m_syt_interval = 16;
503         m_fdf = IEC61883_FDF_SFC_96KHZ;
504         break;
505     case 176400:
506         m_syt_interval = 32;
507         m_fdf = IEC61883_FDF_SFC_176K4HZ;
508         break;
509     case 192000:
510         m_syt_interval = 32;
511         m_fdf = IEC61883_FDF_SFC_192KHZ;
512         break;
513     }
514    
515     iec61883_cip_init (
516         &m_cip_status,
517         IEC61883_FMT_AMDTP,
518         m_fdf,
519         m_framerate,
520         m_dimension,
521         m_syt_interval);
522
523     // allocate the event buffer
524     m_ringbuffer_size_frames=m_nb_buffers * m_period;
525    
526     // add the processing delay
527     m_ringbuffer_size_frames+=RECEIVE_PROCESSING_DELAY_IN_SAMPLES;
528    
529     if( !(m_event_buffer=freebob_ringbuffer_create(
530             (m_dimension * m_ringbuffer_size_frames) * sizeof(quadlet_t)))) {
531         debugFatal("Could not allocate memory event ringbuffer");
532 //              return -ENOMEM;
533         return false;
534     }
535
536     // allocate the temporary cluster buffer
537     if( !(m_cluster_buffer=(char *)calloc(m_dimension,sizeof(quadlet_t)))) {
538         debugFatal("Could not allocate temporary cluster buffer");
539         freebob_ringbuffer_free(m_event_buffer);
540         return false;
541 //              return -ENOMEM;
542     }
543
544     // set the parameters of ports we can:
545     // we want the audio ports to be period buffered,
546     // and the midi ports to be packet buffered
547     for ( PortVectorIterator it = m_Ports.begin();
548           it != m_Ports.end();
549           ++it )
550     {
551         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
552         if(!(*it)->setBufferSize(m_period)) {
553             debugFatal("Could not set buffer size to %d\n",m_period);
554             return false;
555         }
556        
557        
558         switch ((*it)->getPortType()) {
559             case Port::E_Audio:
560                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
561                     debugFatal("Could not set signal type to PeriodSignalling");
562                     return false;
563                 }
564                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
565                 // buffertype and datatype are dependant on the API
566                 if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
567                     debugFatal("Could not set buffer type");
568                     return false;
569                 }
570                 if(!(*it)->useExternalBuffer(true)) {
571                     debugFatal("Could not set external buffer usage");
572                     return false;
573                 }
574                
575                 if(!(*it)->setDataType(Port::E_Float)) {
576                     debugFatal("Could not set data type");
577                     return false;
578                 }
579                
580                
581                 break;
582             case Port::E_Midi:
583                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
584                     debugFatal("Could not set signal type to PeriodSignalling");
585                     return false;
586                 }
587                
588                 // we use a timing unit of 10ns
589                 // this makes sure that for the max syt interval
590                 // we don't have rounding, and keeps the numbers low
591                 // we have 1 slot every 8 events
592                 // we have syt_interval events per packet
593                 // => syt_interval/8 slots per packet
594                 // packet rate is 8000pkt/sec => interval=125us
595                 // so the slot interval is (1/8000)/(syt_interval/8)
596                 // or: 1/(1000 * syt_interval) sec
597                 // which is 1e9/(1000*syt_interval) nsec
598                 // or 100000/syt_interval 'units'
599                 // the event interval is fixed to 320us = 32000 'units'
600                 if(!(*it)->useRateControl(true,(100000/m_syt_interval),32000, false)) {
601                     debugFatal("Could not set signal type to PeriodSignalling");
602                     return false;
603                 }
604                
605                 // buffertype and datatype are dependant on the API
606                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
607                 // buffertype and datatype are dependant on the API
608                 if(!(*it)->setBufferType(Port::E_RingBuffer)) {
609                     debugFatal("Could not set buffer type");
610                     return false;
611                 }
612                 if(!(*it)->setDataType(Port::E_MidiEvent)) {
613                     debugFatal("Could not set data type");
614                     return false;
615                 }
616                 break;
617             default:
618                 debugWarning("Unsupported port type specified\n");
619                 break;
620         }
621     }
622
623     // the API specific settings of the ports should already be set,
624     // as this is called from the processorManager->prepare()
625     // so we can init the ports
626     if(!initPorts()) {
627         debugFatal("Could not initialize ports!\n");
628         return false;
629     }
630
631     if(!preparePorts()) {
632         debugFatal("Could not initialize ports!\n");
633         return false;
634     }
635
636     // we should prefill the event buffer
637     if (!prefill()) {
638         debugFatal("Could not prefill buffers\n");
639         return false;   
640     }
641    
642     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
643     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, FDF: %d, DBS: %d, SYT: %d\n",
644              m_framerate,m_fdf,m_dimension,m_syt_interval);
645     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
646              m_period,m_nb_buffers);
647     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
648              m_port,m_channel);
649
650     return true;
651
652 }
653
654 bool AmdtpTransmitStreamProcessor::transferSilence(unsigned int size) {
655     /* a naive implementation would look like this: */
656    
657     unsigned int write_size=size*sizeof(quadlet_t)*m_dimension;
658     char *dummybuffer=(char *)calloc(sizeof(quadlet_t),size*m_dimension);
659     transmitSilenceBlock(dummybuffer, size, 0);
660
661     if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) {
662         debugWarning("Could not write to event buffer\n");
663     }
664    
665     free(dummybuffer);
666    
667     return true;
668 }
669
670 bool AmdtpTransmitStreamProcessor::transfer() {
671     m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension));
672
673     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
674     // TODO: improve
675 /* a naive implementation would look like this:
676
677     unsigned int write_size=m_period*sizeof(quadlet_t)*m_dimension;
678     char *dummybuffer=(char *)calloc(sizeof(quadlet_t),m_period*m_dimension);
679     transmitBlock(dummybuffer, m_period, 0, 0);
680
681     if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) {
682         debugWarning("Could not write to event buffer\n");
683     }
684
685
686     free(dummybuffer);
687 */
688 /* but we're not that naive anymore... */
689     int xrun;
690     unsigned int offset=0;
691    
692     freebob_ringbuffer_data_t vec[2];
693     // we received one period of frames
694     // this is period_size*dimension of events
695     int events2write=m_period*m_dimension;
696     int bytes2write=events2write*sizeof(quadlet_t);
697
698     /* write events2write bytes to the ringbuffer
699     *  first see if it can be done in one read.
700     *  if so, ok.
701     *  otherwise write up to a multiple of clusters directly to the buffer
702     *  then do the buffer wrap around using ringbuffer_write
703     *  then write the remaining data directly to the buffer in a third pass
704     *  Make sure that we cannot end up on a non-cluster aligned position!
705     */
706     int cluster_size=m_dimension*sizeof(quadlet_t);
707
708     while(bytes2write>0) {
709         int byteswritten=0;
710        
711         unsigned int frameswritten=(m_period*cluster_size-bytes2write)/cluster_size;
712         offset=frameswritten;
713        
714         freebob_ringbuffer_get_write_vector(m_event_buffer, vec);
715            
716         if(vec[0].len==0) { // this indicates a full event buffer
717             debugError("XMT: Event buffer overrun in processor %p\n",this);
718             break;
719         }
720            
721         /* if we don't take care we will get stuck in an infinite loop
722         * because we align to a cluster boundary later
723         * the remaining nb of bytes in one write operation can be
724         * smaller than one cluster
725         * this can happen because the ringbuffer size is always a power of 2
726         */
727         if(vec[0].len<cluster_size) {
728            
729             // encode to the temporary buffer
730             xrun = transmitBlock(m_cluster_buffer, 1, offset);
731            
732             if(xrun<0) {
733                 // xrun detected
734                 debugError("XMT: Frame buffer underrun in processor %p\n",this);
735                 break;
736             }
737                
738             // use the ringbuffer function to write one cluster
739             // the write function handles the wrap around.
740             freebob_ringbuffer_write(m_event_buffer,
741                          m_cluster_buffer,
742                          cluster_size);
743                
744             // we advanced one cluster_size
745             bytes2write-=cluster_size;
746                
747         } else { //
748            
749             if(bytes2write>vec[0].len) {
750                 // align to a cluster boundary
751                 byteswritten=vec[0].len-(vec[0].len%cluster_size);
752             } else {
753                 byteswritten=bytes2write;
754             }
755                
756             xrun = transmitBlock(vec[0].buf,
757                          byteswritten/cluster_size,
758                          offset);
759            
760             if(xrun<0) {
761                     // xrun detected
762                 debugError("XMT: Frame buffer underrun in processor %p\n",this);
763                 break;
764             }
765
766             freebob_ringbuffer_write_advance(m_event_buffer, byteswritten);
767             bytes2write -= byteswritten;
768         }
769
770         // the bytes2write should always be cluster aligned
771         assert(bytes2write%cluster_size==0);
772
773     }
774
775     return true;
776 }
777 /*
778  * write received events to the stream ringbuffers.
779  */
780
781 int AmdtpTransmitStreamProcessor::transmitBlock(char *data,
782                        unsigned int nevents, unsigned int offset)
783 {
784     int problem=0;
785
786     for ( PortVectorIterator it = m_PeriodPorts.begin();
787           it != m_PeriodPorts.end();
788           ++it )
789     {
790
791         if((*it)->isDisabled()) {continue;};
792        
793         //FIXME: make this into a static_cast when not DEBUG?
794
795         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
796         assert(pinfo); // this should not fail!!
797
798         switch(pinfo->getFormat()) {
799         case AmdtpPortInfo::E_MBLA:
800             if(encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
801                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
802                 problem=1;
803             }
804             break;
805         case AmdtpPortInfo::E_SPDIF: // still unimplemented
806             break;
807         default: // ignore
808             break;
809         }
810     }
811     return problem;
812
813 }
814
815 int AmdtpTransmitStreamProcessor::transmitSilenceBlock(char *data,
816                        unsigned int nevents, unsigned int offset)
817 {
818     int problem=0;
819
820     for ( PortVectorIterator it = m_PeriodPorts.begin();
821           it != m_PeriodPorts.end();
822           ++it )
823     {
824
825         //FIXME: make this into a static_cast when not DEBUG?
826
827         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
828         assert(pinfo); // this should not fail!!
829
830         switch(pinfo->getFormat()) {
831         case AmdtpPortInfo::E_MBLA:
832             if(encodeSilencePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
833                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
834                 problem=1;
835             }
836             break;
837         case AmdtpPortInfo::E_SPDIF: // still unimplemented
838             break;
839         default: // ignore
840             break;
841         }
842     }
843     return problem;
844
845 }
846
847 /**
848  * @brief decode a packet for the packet-based ports
849  *
850  * @param data Packet data
851  * @param nevents number of events in data (including events of other ports & port types)
852  * @param dbc DataBlockCount value for this packet
853  * @return true if all successfull
854  */
855 bool AmdtpTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
856 {
857     bool ok=true;
858     char byte;
859    
860     quadlet_t *target_event=NULL;
861     int j;
862    
863     for ( PortVectorIterator it = m_PacketPorts.begin();
864           it != m_PacketPorts.end();
865           ++it )
866     {
867
868 #ifdef DEBUG
869         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
870         assert(pinfo); // this should not fail!!
871
872         // the only packet type of events for AMDTP is MIDI in mbla
873         assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi);
874 #endif
875        
876         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it);
877        
878         // we encode this directly (no function call) due to the high frequency
879         /* idea:
880         spec says: current_midi_port=(dbc+j)%8;
881         => if we start at (dbc+stream->location-1)%8 [due to location_min=1],
882         we'll start at the right event for the midi port.
883         => if we increment j with 8, we stay at the right event.
884         */
885         // FIXME: as we know in advance how big a packet is (syt_interval) we can
886         //        predict how much loops will be present here
887         // first prefill the buffer with NO_DATA's on all time muxed channels
888        
889         for(j = (dbc & 0x07)+mp->getLocation()-1; j < nevents; j += 8) {
890        
891             target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition()));
892            
893             if(mp->canRead()) { // we can send a byte
894                 mp->readEvent(&byte);
895                 *target_event=htonl(
896                     IEC61883_AM824_SET_LABEL((byte)<<16,
897                                              IEC61883_AM824_LABEL_MIDI_1X));
898             } else {
899                 // can't send a byte, either because there is no byte,
900                 // or because this would exceed the maximum rate
901                 *target_event=htonl(
902                     IEC61883_AM824_SET_LABEL(0,IEC61883_AM824_LABEL_MIDI_NO_DATA));
903             }
904         }
905
906     }
907        
908     return ok;
909 }
910
911
912 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents(AmdtpAudioPort *p, quadlet_t *data,
913                        unsigned int offset, unsigned int nevents)
914 {
915     unsigned int j=0;
916
917     quadlet_t *target_event;
918
919     target_event=(quadlet_t *)(data + p->getPosition());
920
921     switch(p->getDataType()) {
922         default:
923         case Port::E_Int24:
924             {
925                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
926
927                 assert(nevents + offset <= p->getBufferSize());
928
929                 buffer+=offset;
930
931                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
932                     *target_event = htonl((*(buffer) & 0x00FFFFFF) | 0x40000000);
933                     buffer++;
934                     target_event += m_dimension;
935                 }
936             }
937             break;
938         case Port::E_Float:
939             {
940                 const float multiplier = (float)(0x7FFFFF00);
941                 float *buffer=(float *)(p->getBufferAddress());
942
943                 assert(nevents + offset <= p->getBufferSize());
944
945                 buffer+=offset;
946
947                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
948    
949                     // don't care for overflow
950                     float v = *buffer * multiplier;  // v: -231 .. 231
951                     unsigned int tmp = ((int)v);
952                     *target_event = htonl((tmp >> 8) | 0x40000000);
953                    
954                     buffer++;
955                     target_event += m_dimension;
956                 }
957             }
958             break;
959     }
960
961     return 0;
962 }
963 int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents(AmdtpAudioPort *p, quadlet_t *data,
964                        unsigned int offset, unsigned int nevents)
965 {
966     unsigned int j=0;
967
968     quadlet_t *target_event;
969
970     target_event=(quadlet_t *)(data + p->getPosition());
971
972     switch(p->getDataType()) {
973         default:
974         case Port::E_Int24:
975         case Port::E_Float:
976             {
977                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
978                     *target_event = htonl(0x40000000);
979                     target_event += m_dimension;
980                 }
981             }
982             break;
983     }
984
985     return 0;
986 }
987
988 /* --------------------- RECEIVE ----------------------- */
989
990 AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int framerate, int dimension)
991     : ReceiveStreamProcessor(port, framerate), m_dimension(dimension), m_last_timestamp(0), m_last_timestamp2(0), m_one_period_passed(false) {
992
993
994 }
995
996 AmdtpReceiveStreamProcessor::~AmdtpReceiveStreamProcessor() {
997     freebob_ringbuffer_free(m_event_buffer);
998     free(m_cluster_buffer);
999
1000 }
1001
1002 bool AmdtpReceiveStreamProcessor::init() {
1003     // call the parent init
1004     // this has to be done before allocating the buffers,
1005     // because this sets the buffersizes from the processormanager
1006     if(!ReceiveStreamProcessor::init()) {
1007         debugFatal("Could not do base class init (%d)\n",this);
1008         return false;
1009     }
1010
1011     return true;
1012 }
1013
1014 enum raw1394_iso_disposition
1015 AmdtpReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,
1016                   unsigned char channel, unsigned char tag, unsigned char sy,
1017                   unsigned int cycle, unsigned int dropped) {
1018    
1019     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
1020    
1021     struct iec61883_packet *packet = (struct iec61883_packet *) data;
1022     assert(packet);
1023         unsigned long in_time=debugGetCurrentTSC();
1024
1025 #ifdef DEBUG
1026     if(dropped>0) {
1027         debugWarning("Dropped %d packets on cycle %d\n",dropped, cycle);
1028     }
1029 #endif
1030    
1031     // how are we going to get this right???
1032 //     m_running=true;
1033    
1034     if((packet->fmt == 0x10) && (packet->fdf != 0xFF) && (packet->syt != 0xFFFF) && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) {
1035         unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
1036        
1037         // signal that we're running
1038                 if(nevents) m_running=true;
1039                
1040                
1041         // do the time stamp processing
1042         // put the last time stamp a variable
1043         // this will allow us to determine the
1044         // actual presentation time later
1045         bool wraparound_occurred=false;
1046        
1047         m_last_timestamp2=m_last_timestamp;
1048        
1049         unsigned int syt_timestamp=ntohs(packet->syt);
1050         // reconstruct the top part of the timestamp using the current cycle number
1051         unsigned int now_cycle_masked=cycle & 0xF;
1052         unsigned int syt_cycle=CYCLE_COUNTER_GET_CYCLES(syt_timestamp);
1053        
1054         // if this is true, wraparound has occurred, undo this wraparound
1055         if(syt_cycle<now_cycle_masked) syt_cycle += 0x10;
1056        
1057         unsigned int delta_cycles=syt_cycle-now_cycle_masked;
1058        
1059         // reconstruct the cycle part of the timestamp
1060         unsigned int new_cycles=cycle + delta_cycles;
1061        
1062         if(new_cycles>7999) {
1063             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Detected wraparound: %d + %d = %d\n",cycle,delta_cycles,new_cycles);
1064            
1065             new_cycles-=8000; // wrap around
1066             wraparound_occurred=true;
1067         }
1068        
1069         m_last_timestamp = (new_cycles) << 12;
1070        
1071         // now add the offset part on top of that
1072         m_last_timestamp |= (syt_timestamp & 0xFFF);
1073        
1074         // mask off the seconds field
1075        
1076         // m_last_timestamp timestamp now contains all info,
1077         // including cycle number
1078        
1079         if (m_last_timestamp && m_last_timestamp2) {
1080             // try and estimate the frame rate from the device:
1081             int measured_difference=((int)(CYCLE_COUNTER_TO_TICKS(m_last_timestamp)))
1082                                      -((int)(CYCLE_COUNTER_TO_TICKS(m_last_timestamp2)));
1083            
1084             // handle wrap around of the cycle variable if nescessary
1085             // it can be that two successive timestamps cause wraparound
1086             // (if the difference between time stamps is larger than 2 cycles),
1087             // thus it isn't always nescessary
1088             if (wraparound_occurred & (m_last_timestamp<m_last_timestamp2)) {
1089                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE," => correcting for timestamp difference wraparound\n");
1090                 measured_difference+=TICKS_PER_SECOND;
1091             }
1092
1093             // implement a 1st order DLL to estimate the framerate
1094             // this is the number of ticks between two samples
1095             float f=measured_difference;
1096             float err = f / (1.0*m_syt_interval) - m_ticks_per_frame;
1097            
1098             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT: %08X | STMP: %08X | DLL: in=%5.0f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, f,m_ticks_per_frame,err);
1099
1100 #ifdef DEBUG
1101             if(f > 1.5*((TICKS_PER_SECOND*1.0) / m_framerate)*m_syt_interval) {
1102                 debugWarning("Timestamp diff more than 50%% of the nominal diff too large!\n");
1103                 debugWarning(" SYT: %08X | STMP: %08X,%08X | DLL: in=%5.0f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, m_last_timestamp2, f,m_ticks_per_frame,err);
1104             }
1105             if(f < 0.5*((TICKS_PER_SECOND*1.0) / m_framerate)*m_syt_interval) {
1106                 debugWarning("Timestamp diff more than 50%% of the nominal diff too small!\n");
1107                 debugWarning(" SYT: %08X | STMP: %08X,%08X | DLL: in=%5.0f, current=%f, err=%e\n",syt_timestamp, m_last_timestamp, m_last_timestamp2, f,m_ticks_per_frame,err);
1108             }
1109 #endif
1110
1111             // integrate the error
1112             m_ticks_per_frame += RECEIVE_DLL_INTEGRATION_COEFFICIENT*err;
1113            
1114         }
1115        
1116          debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"R-SYT for cycle (%2d %2d)=>%2d: %5uT (%04uC + %04uT) %04X %04X %d\n",
1117             cycle,now_cycle_masked,delta_cycles,
1118          CYCLE_COUNTER_TO_TICKS(m_last_timestamp),
1119          CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),
1120          CYCLE_COUNTER_GET_OFFSET(m_last_timestamp),
1121          ntohs(packet->syt),m_last_timestamp&0xFFFF, dropped
1122          );
1123
1124 #ifdef DEBUG
1125         if(m_last_timestamp<m_last_timestamp2) {
1126             if(wraparound_occurred) {
1127                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"timestamp not sequential for cycle %d, but it's wraparound. %08X %08X %08X\n",cycle,syt_timestamp, m_last_timestamp, m_last_timestamp2);                   
1128             } else {
1129                 debugWarning("timestamp not sequential for cycle %d! %08X %08X %08X\n", cycle, syt_timestamp, m_last_timestamp, m_last_timestamp2);
1130                
1131                 // the DLL will recover from this.
1132 //                     ??? m_last_timestamp2=m_last_timestamp-(m_syt_interval*m_ticks_per_frame);
1133             }
1134         }
1135 #endif
1136
1137         // don't process the stream samples when it is not enabled.
1138         if(m_disabled) {
1139             return RAW1394_ISO_DEFER;
1140         }
1141         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n");
1142        
1143         unsigned int write_size=nevents*sizeof(quadlet_t)*m_dimension;
1144         // add the data payload to the ringbuffer
1145        
1146         if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size)
1147         {
1148             debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",
1149                  cycle, m_framecounter, m_handler->getPacketCount());
1150             m_xruns++;
1151
1152             retval=RAW1394_ISO_DEFER;
1153         } else {
1154             retval=RAW1394_ISO_OK;
1155             // process all ports that should be handled on a per-packet base
1156             // this is MIDI for AMDTP (due to the need of DBC)
1157             if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) {
1158                 debugWarning("Problem decoding Packet Ports\n");
1159                 retval=RAW1394_ISO_DEFER;
1160             }
1161
1162         }
1163
1164 #ifdef DEBUG
1165         if(packet->dbs) {
1166             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
1167                 "RCV %04d: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",
1168                 cycle, channel, packet->fdf,
1169                 packet->syt,
1170                 packet->dbs,
1171                 packet->dbc,
1172                 packet->fmt,
1173                 length,
1174                 ((length / sizeof (quadlet_t)) - 2)/packet->dbs);
1175         }
1176 #endif
1177
1178         // update the frame counter
1179         incrementFrameCounter(nevents);
1180         if(m_framecounter>(signed int)m_period) {
1181            retval=RAW1394_ISO_DEFER;
1182            debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"defer!\n");
1183         }
1184
1185     } else {
1186         // discard packet
1187         // can be important for sync though
1188        
1189         // FIXME: this is to prevent libraw to do loop over too
1190         //        much packets at once (draining the xmit side)
1191         //        but putting it here is a little arbitrary
1192         retval=RAW1394_ISO_DEFER;
1193     }
1194    
1195     m_PacketStat.mark(debugGetCurrentTSC()-in_time);
1196    
1197 //     m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension));
1198    
1199     return retval;
1200 }
1201
1202 // this uses SYT to determine if one period is ready
1203 bool AmdtpReceiveStreamProcessor::isOnePeriodReady() {
1204
1205 #ifdef DO_SYT_SYNC
1206  // this code is not ready yet
1207
1208     // one sample will take a number off cycle counter ticks:
1209     // The number of ticks per second is 24576000
1210     // The number of samples per second is Fs
1211     // therefore the number of ticks per sample is 24576000 / Fs
1212     // NOTE: this will be rounded!!
1213 //     float ticks_per_sample=24576000.0/m_framerate;
1214      float ticks_per_sample=m_ticks_per_frame;
1215
1216     // we are allowed to add some constant
1217     // processing delay to the transfer delay
1218     // being the period size and some fixed delay
1219 //     unsigned int processing_delay=ticks_per_sample*(m_period)+RECEIVE_PROCESSING_DELAY;
1220     unsigned int processing_delay=ticks_per_sample*(m_period+RECEIVE_PROCESSING_DELAY_IN_SAMPLES);
1221    
1222     // the number of events in the buffer is
1223     // m_framecounter
1224
1225     // we have the timestamp of the last event block:
1226     // m_last_timestamp
1227    
1228     // the time at which the beginning of the buffer should be
1229     // presented to the audio side is:
1230     // m_last_timestamp - (m_framecounter-m_syt_interval)*ticks_per_sample
1231    
1232     // NOTE: in fact, we don't have to check this, because it should always be the case
1233     //
1234     // WAS: however we have to make sure that we can transfer at least one period
1235     // therefore we first check if this is ok
1236    
1237 //      if(m_framecounter > (signed int)m_period) {
1238
1239         unsigned int m_last_timestamp_ticks = CYCLE_COUNTER_TO_TICKS(m_last_timestamp);
1240        
1241         // add the processing delay
1242         int ideal_presentation_time = m_last_timestamp_ticks + processing_delay;
1243         int buffer_content_ticks=((int)m_framecounter)-((int)m_syt_interval);
1244         buffer_content_ticks *= ticks_per_sample;
1245        
1246         // if the ideal_presentation_time is smaller than buffer_content_ticks, wraparound has occurred
1247         // for the cycle part of m_last_timestamp. Therefore add one second worth of ticks
1248         // to the cycle counter, as this is the wraparound point.
1249         if (ideal_presentation_time < buffer_content_ticks) ideal_presentation_time += 24576000;
1250         // we can now safely substract these, it will always be > 0
1251         ideal_presentation_time -= buffer_content_ticks;
1252        
1253         // FIXME: if we are sure, make ideal_presentation_time an unsigned int
1254 //         assert(ideal_presentation_time>=0);
1255        
1256         unsigned int current_time_ticks = (m_handler->getCycleCounter() % TICKS_PER_SECOND );
1257
1258 #ifdef DEBUG
1259         if(ideal_presentation_time<0) {
1260             debugWarning("ideal_presentation_time time is negative!\n");
1261             debugOutput(DEBUG_LEVEL_VERBOSE,"Periods: %d, FC: %d, remote framerate %f\n",
1262                 m_PeriodStat.m_count, m_framecounter, m_ticks_per_frame);
1263             debugOutput(DEBUG_LEVEL_VERBOSE,"p-delay: %u, buffer_content: %d\n",
1264                 processing_delay, buffer_content_ticks);
1265             debugOutput(DEBUG_LEVEL_VERBOSE,"Timestamp : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n",
1266                 m_last_timestamp_ticks,
1267                 CYCLE_COUNTER_GET_SECS(m_last_timestamp),
1268                 CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),
1269                 CYCLE_COUNTER_GET_OFFSET(m_last_timestamp)
1270                 );
1271             debugOutput(DEBUG_LEVEL_VERBOSE,"P-TIME    : %10d ticks (%3u secs + %4u cycles + %04u ticks)\n",
1272                 ideal_presentation_time,
1273                 TICKS_TO_SECS(ideal_presentation_time),
1274                 TICKS_TO_CYCLES(ideal_presentation_time),
1275                 TICKS_TO_OFFSET(ideal_presentation_time)
1276                 );
1277             debugOutput(DEBUG_LEVEL_VERBOSE,"Now       : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n",
1278                 current_time_ticks,
1279                 TICKS_TO_SECS(current_time_ticks),
1280                 TICKS_TO_CYCLES(current_time_ticks),
1281                 TICKS_TO_OFFSET(current_time_ticks)
1282                 );
1283             return false;
1284         }
1285         if(ideal_presentation_time<m_last_timestamp_ticks) {
1286             debugWarning("ideal_presentation_time earlier than last timestamp!\n");
1287             debugOutput(DEBUG_LEVEL_VERBOSE,"Periods: %d, FC: %d, remote framerate %f\n",
1288                 m_PeriodStat.m_count, m_framecounter, m_ticks_per_frame);
1289             debugOutput(DEBUG_LEVEL_VERBOSE,"p-delay: %u, buffer_content: %u\n",
1290                 processing_delay, buffer_content_ticks);
1291             debugOutput(DEBUG_LEVEL_VERBOSE,"Timestamp : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n",
1292                 m_last_timestamp_ticks,
1293                 CYCLE_COUNTER_GET_SECS(m_last_timestamp),
1294                 CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),
1295                 CYCLE_COUNTER_GET_OFFSET(m_last_timestamp)
1296                 );
1297             debugOutput(DEBUG_LEVEL_VERBOSE,"P-TIME    : %10d ticks (%3u secs + %4u cycles + %04u ticks)\n",
1298                 ideal_presentation_time,
1299                 TICKS_TO_SECS(ideal_presentation_time),
1300                 TICKS_TO_CYCLES(ideal_presentation_time),
1301                 TICKS_TO_OFFSET(ideal_presentation_time)
1302                 );
1303             debugOutput(DEBUG_LEVEL_VERBOSE,"Now       : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n",
1304                 current_time_ticks,
1305                 TICKS_TO_SECS(current_time_ticks),
1306                 TICKS_TO_CYCLES(current_time_ticks),
1307                 TICKS_TO_OFFSET(current_time_ticks)
1308                 );
1309                        
1310         }
1311 #endif
1312        
1313         // if the last signalled period lies in the future, we know we had wraparound of the clock
1314         // so add one second
1315 //         if (current_time_ticks < m_previous_signal_ticks) current_time_ticks += 24576000;
1316         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Periods: %d, remote framerate %f\n",m_PeriodStat.m_count, m_ticks_per_frame);
1317         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Timestamp : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n",
1318             m_last_timestamp_ticks,
1319             CYCLE_COUNTER_GET_SECS(m_last_timestamp),
1320             CYCLE_COUNTER_GET_CYCLES(m_last_timestamp),
1321             CYCLE_COUNTER_GET_OFFSET(m_last_timestamp)
1322             );
1323         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"P-TIME    : %10d ticks (%3u secs + %4u cycles + %04u ticks)\n",
1324             ideal_presentation_time,
1325             ideal_presentation_time/24576000,
1326             (ideal_presentation_time/3072) % 8000,
1327             ideal_presentation_time%3072
1328             );
1329         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Now       : %10u ticks (%3u secs + %4u cycles + %04u ticks)\n",
1330             current_time_ticks,
1331             TICKS_TO_SECS(current_time_ticks),
1332             TICKS_TO_CYCLES(current_time_ticks),
1333             TICKS_TO_OFFSET(current_time_ticks)
1334             );
1335        
1336         int tmp=ideal_presentation_time-current_time_ticks;
1337        
1338         // if current_time_ticks wraps around while ahead of the presentation time, we have
1339         // a problem.
1340         // we know however that we have to wait for at max one buffer + some transmit delay
1341         // therefore we clip this value at 0.5 seconds
1342         if (tmp > 24576000/2) tmp-=24576000;
1343        
1344         if(tmp<0) {
1345             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"SYT passed (%d ticks too late)\n",-tmp);
1346             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Periods: %d, remote ticks/frame: %f, remote framerate = %f\n",
1347                 m_PeriodStat.m_count, m_ticks_per_frame, 24576000.0/m_ticks_per_frame);
1348             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Bufferfill %d, framecounter %d\n",
1349                 freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension),m_framecounter);
1350             if (-tmp>1000000) debugWarning("SYT VERY LATE: %d!\n",-tmp);
1351            
1352             m_WakeupStat.mark(m_framecounter);
1353            
1354             m_one_period_passed=true;
1355             m_last_timestamp_at_period_ticks=ideal_presentation_time;
1356            
1357             return true;
1358         } else {
1359             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"Too early wait %d ticks\n",tmp);
1360              return false;
1361         }
1362 //      } else {
1363 //         return false;
1364 //      }
1365 #else
1366     if(m_framecounter > m_period) {
1367      return true;
1368     } else return false;
1369 #endif
1370 }
1371
1372 unsigned int AmdtpReceiveStreamProcessor::getPeriodTimeStamp() {
1373     if (m_one_period_passed) {
1374         return m_last_timestamp_at_period_ticks;
1375     } else {
1376         //     float ticks_per_sample=24576000.0/m_framerate;
1377          float ticks_per_sample=m_ticks_per_frame;
1378    
1379         // we are allowed to add some constant
1380         // processing delay to the transfer delay
1381         // being the period size and some fixed delay
1382         //     unsigned int processing_delay=ticks_per_sample*(m_period)+RECEIVE_PROCESSING_DELAY;
1383         unsigned int processing_delay=ticks_per_sample*(m_period+RECEIVE_PROCESSING_DELAY_IN_SAMPLES);
1384        
1385         unsigned int m_last_timestamp_ticks = CYCLE_COUNTER_TO_TICKS(m_last_timestamp);
1386        
1387         // add the processing delay
1388         int ideal_presentation_time = m_last_timestamp_ticks + processing_delay;
1389         unsigned int buffer_content_ticks=(int)((m_framecounter-m_syt_interval)*ticks_per_sample);
1390        
1391         // if the ideal_presentation_time is smaller than buffer_content_ticks, wraparound has occurred
1392         // for the cycle part of m_last_timestamp. Therefore add one second worth of ticks
1393         // to the cycle counter, as this is the wraparound point.
1394         if (ideal_presentation_time < buffer_content_ticks) ideal_presentation_time += 24576000;
1395         // we can now safely substract these, it will always be > 0
1396         ideal_presentation_time -= buffer_content_ticks;
1397        
1398         return ideal_presentation_time;
1399     }
1400 }
1401
1402 void AmdtpReceiveStreamProcessor::dumpInfo()
1403 {
1404
1405     StreamProcessor::dumpInfo();
1406    
1407         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Device framerate  : %f\n", 24576000.0/m_ticks_per_frame);
1408
1409 }
1410
1411
1412 void AmdtpReceiveStreamProcessor::setVerboseLevel(int l) {
1413         setDebugLevel(l);
1414         ReceiveStreamProcessor::setVerboseLevel(l);
1415
1416 }
1417
1418
1419 bool AmdtpReceiveStreamProcessor::reset() {
1420
1421     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
1422
1423     // reset the event buffer, discard all content
1424     freebob_ringbuffer_reset(m_event_buffer);
1425    
1426         // reset the last timestamp
1427         m_last_timestamp=0;
1428        
1429     m_PeriodStat.reset();
1430     m_PacketStat.reset();
1431     m_WakeupStat.reset();
1432
1433     // reset the framerate estimate
1434      m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / m_framerate;
1435
1436      debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n",m_ticks_per_frame);
1437        
1438         //reset the timestamps
1439         m_last_timestamp=0;
1440         m_last_timestamp2=0;
1441        
1442     m_one_period_passed=false;
1443
1444     // reset all non-device specific stuff
1445     // i.e. the iso stream and the associated ports
1446     if(!ReceiveStreamProcessor::reset()) {
1447             debugFatal("Could not do base class reset\n");
1448             return false;
1449     }
1450     return true;
1451 }
1452
1453 bool AmdtpReceiveStreamProcessor::prepare() {
1454
1455     m_PeriodStat.setName("RCV PERIOD");
1456     m_PacketStat.setName("RCV PACKET");
1457     m_WakeupStat.setName("RCV WAKEUP");
1458
1459         // prepare all non-device specific stuff
1460         // i.e. the iso stream and the associated ports
1461         if(!ReceiveStreamProcessor::prepare()) {
1462                 debugFatal("Could not prepare base class\n");
1463                 return false;
1464         }
1465        
1466         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
1467         switch (m_framerate) {
1468         case 32000:
1469                 m_syt_interval = 8;
1470                 break;
1471         case 44100:
1472                 m_syt_interval = 8;
1473                 break;
1474         default:
1475         case 48000:
1476                 m_syt_interval = 8;
1477                 break;
1478         case 88200:
1479                 m_syt_interval = 16;
1480                 break;
1481         case 96000:
1482                 m_syt_interval = 16;
1483                 break;
1484         case 176400:
1485                 m_syt_interval = 32;
1486                 break;
1487         case 192000:
1488                 m_syt_interval = 32;
1489                 break;
1490         }
1491
1492     // prepare the framerate estimate
1493     m_ticks_per_frame = (TICKS_PER_SECOND*1.0) / m_framerate;
1494
1495     debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n",m_ticks_per_frame);
1496
1497     // allocate the event buffer
1498     unsigned int ringbuffer_size_frames=m_nb_buffers * m_period;
1499    
1500     // add the processing delay
1501     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding %u frames of SYT slack buffering...\n",
1502         RECEIVE_PROCESSING_DELAY_IN_SAMPLES);
1503     ringbuffer_size_frames+=RECEIVE_PROCESSING_DELAY_IN_SAMPLES;
1504    
1505     if( !(m_event_buffer=freebob_ringbuffer_create(
1506             (m_dimension * ringbuffer_size_frames) * sizeof(quadlet_t)))) {
1507                 debugFatal("Could not allocate memory event ringbuffer");
1508                 return false;
1509         }
1510
1511         // allocate the temporary cluster buffer
1512         if( !(m_cluster_buffer=(char *)calloc(m_dimension,sizeof(quadlet_t)))) {
1513                 debugFatal("Could not allocate temporary cluster buffer");
1514                 freebob_ringbuffer_free(m_event_buffer);
1515                 return false;
1516         }
1517
1518         // set the parameters of ports we can:
1519         // we want the audio ports to be period buffered,
1520         // and the midi ports to be packet buffered
1521         for ( PortVectorIterator it = m_Ports.begin();
1522                   it != m_Ports.end();
1523                   ++it )
1524         {
1525                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
1526                 if(!(*it)->setBufferSize(m_period)) {
1527                         debugFatal("Could not set buffer size to %d\n",m_period);
1528                         return false;
1529                 }
1530
1531                 switch ((*it)->getPortType()) {
1532                         case Port::E_Audio:
1533                                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
1534                                         debugFatal("Could not set signal type to PeriodSignalling");
1535                                         return false;
1536                                 }
1537                                 // buffertype and datatype are dependant on the API
1538                                 debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");
1539                                 // buffertype and datatype are dependant on the API
1540                                 if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
1541                                         debugFatal("Could not set buffer type");
1542                                         return false;
1543                                 }
1544                                 if(!(*it)->useExternalBuffer(true)) {
1545                                         debugFatal("Could not set external buffer usage");
1546                                         return false;
1547                                 }
1548                                 if(!(*it)->setDataType(Port::E_Float)) {
1549                                         debugFatal("Could not set data type");
1550                                         return false;
1551                                 }
1552                                 break;
1553                         case Port::E_Midi:
1554                                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
1555                                         debugFatal("Could not set signal type to PacketSignalling");
1556                                         return false;
1557                                 }
1558                                 // buffertype and datatype are dependant on the API
1559                                 // buffertype and datatype are dependant on the API
1560                                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
1561                                 // buffertype and datatype are dependant on the API
1562                                 if(!(*it)->setBufferType(Port::E_RingBuffer)) {
1563                                         debugFatal("Could not set buffer type");
1564                                         return false;
1565                                 }
1566                                 if(!(*it)->setDataType(Port::E_MidiEvent)) {
1567                                         debugFatal("Could not set data type");
1568                                         return false;
1569                                 }
1570                                 break;
1571                         default:
1572                                 debugWarning("Unsupported port type specified\n");
1573                                 break;
1574                 }
1575
1576         }
1577
1578         // the API specific settings of the ports should already be set,
1579         // as this is called from the processorManager->prepare()
1580         // so we can init the ports
1581         if(!initPorts()) {
1582                 debugFatal("Could not initialize ports!\n");
1583                 return false;
1584         }
1585
1586         if(!preparePorts()) {
1587                 debugFatal("Could not initialize ports!\n");
1588                 return false;
1589         }
1590
1591
1592         debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
1593         debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, DBS: %d, SYT: %d\n",
1594                      m_framerate,m_dimension,m_syt_interval);
1595         debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
1596                      m_period,m_nb_buffers);
1597         debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
1598                      m_port,m_channel);
1599         return true;
1600
1601 }
1602
1603 bool AmdtpReceiveStreamProcessor::transfer() {
1604
1605     m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension));
1606
1607         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
1608        
1609 /* another naive section:       
1610         unsigned int read_size=m_period*sizeof(quadlet_t)*m_dimension;
1611         char *dummybuffer=(char *)calloc(sizeof(quadlet_t),m_period*m_dimension);
1612         if (freebob_ringbuffer_read(m_event_buffer,(char *)(dummybuffer),read_size) < read_size) {
1613                 debugWarning("Could not read from event buffer\n");
1614         }
1615
1616         receiveBlock(dummybuffer, m_period, 0);
1617
1618         free(dummybuffer);
1619 */
1620         int xrun;
1621         unsigned int offset=0;
1622        
1623         freebob_ringbuffer_data_t vec[2];
1624         // we received one period of frames on each connection
1625         // this is period_size*dimension of events
1626
1627         int events2read=m_period*m_dimension;
1628         int bytes2read=events2read*sizeof(quadlet_t);
1629         /* read events2read bytes from the ringbuffer
1630         *  first see if it can be done in one read.
1631         *  if so, ok.
1632         *  otherwise read up to a multiple of clusters directly from the buffer
1633         *  then do the buffer wrap around using ringbuffer_read
1634         *  then read the remaining data directly from the buffer in a third pass
1635         *  Make sure that we cannot end up on a non-cluster aligned position!
1636         */
1637         int cluster_size=m_dimension*sizeof(quadlet_t);
1638        
1639         while(bytes2read>0) {
1640                 unsigned int framesread=(m_period*cluster_size-bytes2read)/cluster_size;
1641                 offset=framesread;
1642                
1643                 int bytesread=0;
1644
1645                 freebob_ringbuffer_get_read_vector(m_event_buffer, vec);
1646                        
1647                 if(vec[0].len==0) { // this indicates an empty event buffer
1648                         debugError("RCV: Event buffer underrun in processor %p\n",this);
1649                         break;
1650                 }
1651                        
1652                 /* if we don't take care we will get stuck in an infinite loop
1653                 * because we align to a cluster boundary later
1654                 * the remaining nb of bytes in one read operation can be smaller than one cluster
1655                 * this can happen because the ringbuffer size is always a power of 2
1656                         */
1657                 if(vec[0].len<cluster_size) {
1658                         // use the ringbuffer function to read one cluster
1659                         // the read function handles wrap around
1660                         freebob_ringbuffer_read(m_event_buffer,m_cluster_buffer,cluster_size);
1661
1662                         xrun = receiveBlock(m_cluster_buffer, 1, offset);
1663                                
1664                         if(xrun<0) {
1665                                 // xrun detected
1666                                 debugError("RCV: Frame buffer overrun in processor %p\n",this);
1667                                 break;
1668                         }
1669                                
1670                                 // we advanced one cluster_size
1671                         bytes2read-=cluster_size;
1672                                
1673                 } else { //
1674                        
1675                         if(bytes2read>vec[0].len) {
1676                                         // align to a cluster boundary
1677                                 bytesread=vec[0].len-(vec[0].len%cluster_size);
1678                         } else {
1679                                 bytesread=bytes2read;
1680                         }
1681                                
1682                         xrun = receiveBlock(vec[0].buf, bytesread/cluster_size, offset);
1683                                
1684                         if(xrun<0) {
1685                                         // xrun detected
1686                                 debugError("RCV: Frame buffer overrun in processor %p\n",this);
1687                                 break;
1688                         }
1689
1690                         freebob_ringbuffer_read_advance(m_event_buffer, bytesread);
1691                         bytes2read -= bytesread;
1692                 }
1693                        
1694                 // the bytes2read should always be cluster aligned
1695                 assert(bytes2read%cluster_size==0);
1696         }
1697
1698         return true;
1699 }
1700
1701 /**
1702  * \brief write received events to the stream ringbuffers.
1703  */
1704 int AmdtpReceiveStreamProcessor::receiveBlock(char *data,
1705                                            unsigned int nevents, unsigned int offset)
1706 {
1707         int problem=0;
1708
1709         for ( PortVectorIterator it = m_PeriodPorts.begin();
1710           it != m_PeriodPorts.end();
1711           ++it )
1712     {
1713
1714         if((*it)->isDisabled()) {continue;};
1715
1716                 //FIXME: make this into a static_cast when not DEBUG?
1717
1718                 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
1719                 assert(pinfo); // this should not fail!!
1720
1721                 switch(pinfo->getFormat()) {
1722                 case AmdtpPortInfo::E_MBLA:
1723                         if(decodeMBLAEventsToPort(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
1724                                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str());
1725                                 problem=1;
1726                         }
1727                         break;
1728                 case AmdtpPortInfo::E_SPDIF: // still unimplemented
1729                         break;
1730         /* for this processor, midi is a packet based port
1731                 case AmdtpPortInfo::E_Midi:
1732                         break;*/
1733                 default: // ignore
1734                         break;
1735                 }
1736     }
1737         return problem;
1738
1739 }
1740
1741 /**
1742  * @brief decode a packet for the packet-based ports
1743  *
1744  * @param data Packet data
1745  * @param nevents number of events in data (including events of other ports & port types)
1746  * @param dbc DataBlockCount value for this packet
1747  * @return true if all successfull
1748  */
1749 bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
1750 {
1751         bool ok=true;
1752        
1753         quadlet_t *target_event=NULL;
1754         int j;
1755        
1756         for ( PortVectorIterator it = m_PacketPorts.begin();
1757           it != m_PacketPorts.end();
1758           ++it )
1759         {
1760
1761 #ifdef DEBUG
1762                 AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
1763                 assert(pinfo); // this should not fail!!
1764
1765                 // the only packet type of events for AMDTP is MIDI in mbla
1766                 assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi);
1767 #endif
1768                 AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it);
1769                
1770                 // we decode this directly (no function call) due to the high frequency
1771                 /* idea:
1772                 spec says: current_midi_port=(dbc+j)%8;
1773                 => if we start at (dbc+stream->location-1)%8 [due to location_min=1],
1774                 we'll start at the right event for the midi port.
1775                 => if we increment j with 8, we stay at the right event.
1776                 */
1777                 // FIXME: as we know in advance how big a packet is (syt_interval) we can
1778                 //        predict how much loops will be present here
1779                 for(j = (dbc & 0x07)+mp->getLocation()-1; j < nevents; j += 8) {
1780                         target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition()));
1781                         quadlet_t sample_int=ntohl(*target_event);
1782                         // FIXME: this assumes that 2X and 3X speed isn't used,
1783                         // because only the 1X slot is put into the ringbuffer
1784                         if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) {
1785                                 sample_int=(sample_int >> 16) & 0x000000FF;
1786                                 if(!mp->writeEvent(&sample_int)) {
1787                                         debugWarning("Packet port events lost\n");
1788                                         ok=false;
1789                                 }
1790                         }
1791                 }
1792
1793         }
1794        
1795         return ok;
1796 }
1797
1798 int AmdtpReceiveStreamProcessor::decodeMBLAEventsToPort(AmdtpAudioPort *p, quadlet_t *data,
1799                                            unsigned int offset, unsigned int nevents)
1800 {
1801         unsigned int j=0;
1802
1803 //      printf("****************\n");
1804 //      hexDumpQuadlets(data,m_dimension*4);
1805 //      printf("****************\n");
1806
1807         quadlet_t *target_event;
1808
1809         target_event=(quadlet_t *)(data + p->getPosition());
1810
1811         switch(p->getDataType()) {
1812                 default:
1813                 case Port::E_Int24:
1814                         {
1815                                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
1816
1817                                 assert(nevents + offset <= p->getBufferSize());
1818
1819                                 buffer+=offset;
1820
1821                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
1822                                         *(buffer)=(ntohl((*target_event) ) & 0x00FFFFFF);
1823                                         buffer++;
1824                                         target_event+=m_dimension;
1825                                 }
1826                         }
1827                         break;
1828                 case Port::E_Float:
1829                         {
1830                                 const float multiplier = 1.0f / (float)(0x7FFFFF);
1831                                 float *buffer=(float *)(p->getBufferAddress());
1832
1833                                 assert(nevents + offset <= p->getBufferSize());
1834
1835                                 buffer+=offset;
1836
1837                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
1838        
1839                                         unsigned int v = ntohl(*target_event) & 0x00FFFFFF;
1840                                         // sign-extend highest bit of 24-bit int
1841                                         int tmp = (int)(v << 8) / 256;
1842                
1843                                         *buffer = tmp * multiplier;
1844                                
1845                                         buffer++;
1846                                         target_event+=m_dimension;
1847                                 }
1848                         }
1849                         break;
1850         }
1851
1852         return 0;
1853 }
1854
1855 } // end of namespace FreebobStreaming
Note: See TracBrowser for help on using the browser.