root/branches/ppalmers-streaming/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp

Revision 715, 22.4 kB (checked in by ppalmers, 16 years ago)

some more cleaning

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "AmdtpReceiveStreamProcessor.h"
25 #include "AmdtpPort.h"
26 #include "../StreamProcessorManager.h"
27
28 #include "../util/cycletimer.h"
29
30 #include <netinet/in.h>
31 #include <assert.h>
32
33 // in ticks
34 // as per AMDTP2.1:
35 // 354.17us + 125us @ 24.576ticks/usec = 11776.08192 ticks
36 #define DEFAULT_TRANSFER_DELAY (11776U)
37
38 #define TRANSMIT_TRANSFER_DELAY DEFAULT_TRANSFER_DELAY
39
40 namespace Streaming {
41
42 /* --------------------- RECEIVE ----------------------- */
43
44 AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int port, int dimension)
45     : StreamProcessor(ePT_Receive , port)
46     , m_dimension(dimension)
47     , m_last_timestamp(0)
48     , m_last_timestamp2(0)
49     , m_dropped(0)
50 {}
51
52 bool AmdtpReceiveStreamProcessor::init() {
53
54     // call the parent init
55     // this has to be done before allocating the buffers,
56     // because this sets the buffersizes from the processormanager
57     if(!StreamProcessor::init()) {
58         debugFatal("Could not do base class init (%d)\n",this);
59         return false;
60     }
61     return true;
62 }
63
64 enum raw1394_iso_disposition
65 AmdtpReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,
66                   unsigned char channel, unsigned char tag, unsigned char sy,
67                   unsigned int cycle, unsigned int dropped) {
68
69     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
70
71     int dropped_cycles=diffCycles(cycle, m_last_cycle) - 1;
72     if (dropped_cycles < 0) debugWarning("(%p) dropped < 1 (%d)\n", this, dropped_cycles);
73     else m_dropped += dropped_cycles;
74     if (dropped_cycles > 0) debugWarning("(%p) dropped %d packets on cycle %u\n", this, dropped_cycles, cycle);
75
76     m_last_cycle=cycle;
77
78     struct iec61883_packet *packet = (struct iec61883_packet *) data;
79     assert(packet);
80
81 #ifdef DEBUG
82     if(dropped>0) {
83         debugWarning("(%p) Dropped %d packets on cycle %d\n", this, dropped, cycle);
84     }
85
86     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"ch%2u: CY=%4u, SYT=%08X (%4ucy + %04uticks) (running=%d)\n",
87         channel, cycle, ntohs(packet->syt),
88         CYCLE_TIMER_GET_CYCLES(ntohs(packet->syt)), CYCLE_TIMER_GET_OFFSET(ntohs(packet->syt)),
89         m_running);
90
91     debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
92         "RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d\n",
93         channel, packet->fdf,
94         packet->syt,
95         packet->dbs,
96         packet->dbc,
97         packet->fmt,
98         length);
99
100 #endif
101
102     // check if this is a valid packet
103     if((packet->syt != 0xFFFF)
104        && (packet->fdf != 0xFF)
105        && (packet->fmt == 0x10)
106        && (packet->dbs>0)
107        && (length>=2*sizeof(quadlet_t))) {
108
109         unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
110
111         //=> store the previous timestamp
112         m_last_timestamp2=m_last_timestamp;
113
114         uint64_t nowX = m_handler->getCycleTimer();
115         //=> convert the SYT to a full timestamp in ticks
116         m_last_timestamp=sytRecvToFullTicks((uint32_t)ntohs(packet->syt),
117                                         cycle, nowX);
118
119         int64_t diffx = diffTicks(m_last_timestamp, m_last_timestamp2);
120         if (abs(diffx) > m_syt_interval * m_data_buffer->getRate() * 1.1) {
121             uint32_t now=m_handler->getCycleTimer();
122             uint32_t syt = (uint32_t)ntohs(packet->syt);
123             uint32_t now_ticks=CYCLE_TIMER_TO_TICKS(now);
124            
125             debugOutput(DEBUG_LEVEL_VERBOSE, "diff=%06lld TS=%011llu TS2=%011llu\n",
126                 diffx, m_last_timestamp, m_last_timestamp2);
127             debugOutput(DEBUG_LEVEL_VERBOSE, "[1] cy=%04d dropped=%05llu syt=%04llX NOW=%08llX => TS=%011llu\n",
128                 m_last_good_cycle, m_last_dropped, m_last_syt, m_last_now, m_last_timestamp2);
129             debugOutput(DEBUG_LEVEL_VERBOSE, "[2] cy=%04d dropped=%05d syt=%04X NOW=%08llX => TS=%011llu\n",
130                 cycle, dropped_cycles, ntohs(packet->syt), nowX, m_last_timestamp);
131
132             uint32_t test_ts=sytRecvToFullTicks(syt, cycle, now);
133
134             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: SYT=%08X,            CY=%04d OFF=%04d\n",
135                 cycle, syt, CYCLE_TIMER_GET_CYCLES(syt), CYCLE_TIMER_GET_OFFSET(syt)
136                 );
137             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: NOW=%011lu, SEC=%03u CY=%04u OFF=%04u\n",
138                 cycle, now_ticks, CYCLE_TIMER_GET_SECS(now), CYCLE_TIMER_GET_CYCLES(now), CYCLE_TIMER_GET_OFFSET(now)
139                 );
140             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: TSS=%011lu, SEC=%03u CY=%04u OFF=%04u\n",
141                 cycle, test_ts, TICKS_TO_SECS(test_ts), TICKS_TO_CYCLES(test_ts), TICKS_TO_OFFSET(test_ts)
142                 );
143                
144             int64_t diff_ts = diffTicks(now_ticks, test_ts);
145             debugOutput(DEBUG_LEVEL_VERBOSE, "DIFF  : TCK=%011lld, SEC=%03llu CY=%04llu OFF=%04llu\n",
146                 diff_ts,
147                 TICKS_TO_SECS((uint64_t)diff_ts),
148                 TICKS_TO_CYCLES((uint64_t)diff_ts),
149                 TICKS_TO_OFFSET((uint64_t)diff_ts)
150                 );
151         }
152         m_last_syt = ntohs(packet->syt);
153         m_last_now = nowX;
154         m_last_good_cycle = cycle;
155         m_last_dropped = dropped_cycles;
156
157         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "RECV: CY=%04u TS=%011llu\n",
158                 cycle, m_last_timestamp);
159
160         // we have to keep in mind that there are also
161         // some packets buffered by the ISO layer,
162         // at most x=m_handler->getWakeupInterval()
163         // these contain at most x*syt_interval
164         // frames, meaning that we might receive
165         // this packet x*syt_interval*ticks_per_frame
166         // later than expected (the real receive time)
167         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"STMP: %lluticks | buff=%d, syt_interval=%d, tpf=%f\n",
168             m_last_timestamp, m_handler->getWakeupInterval(),m_syt_interval,getTicksPerFrame());
169
170         //=> signal that we're running (if we are)
171         if(!m_running && nevents && m_last_timestamp2 && m_last_timestamp) {
172             debugOutput(DEBUG_LEVEL_VERBOSE,"Receive StreamProcessor %p started running at %d\n", this, cycle);
173             m_running=true;
174             m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
175             // we don't want this first sample to be written
176             return RAW1394_ISO_OK;
177         }
178
179         // if we are not running yet, there is nothing more to do
180         if(!m_running) {
181             return RAW1394_ISO_OK;
182         }
183         #ifdef DEBUG_OFF
184         if((cycle % 1000) == 0) {
185             uint32_t now=m_handler->getCycleTimer();
186             uint32_t syt = (uint32_t)ntohs(packet->syt);
187             uint32_t now_ticks=CYCLE_TIMER_TO_TICKS(now);
188
189             uint32_t test_ts=sytRecvToFullTicks(syt, cycle, now);
190
191             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: SYT=%08X,            CY=%02d OFF=%04d\n",
192                 cycle, syt, CYCLE_TIMER_GET_CYCLES(syt), CYCLE_TIMER_GET_OFFSET(syt)
193                 );
194             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: NOW=%011lu, SEC=%03u CY=%02u OFF=%04u\n",
195                 cycle, now_ticks, CYCLE_TIMER_GET_SECS(now), CYCLE_TIMER_GET_CYCLES(now), CYCLE_TIMER_GET_OFFSET(now)
196                 );
197             debugOutput(DEBUG_LEVEL_VERBOSE, "R %04d: TSS=%011lu, SEC=%03u CY=%02u OFF=%04u\n",
198                 cycle, test_ts, TICKS_TO_SECS(test_ts), TICKS_TO_CYCLES(test_ts), TICKS_TO_OFFSET(test_ts)
199                 );
200         }
201         #endif
202
203         #ifdef DEBUG
204             // keep track of the lag
205             uint32_t now=m_handler->getCycleTimer();
206             int32_t diff = diffCycles( cycle,  ((int)CYCLE_TIMER_GET_CYCLES(now)) );
207             m_PacketStat.mark(diff);
208         #endif
209
210         //=> process the packet
211         // add the data payload to the ringbuffer
212        
213         if(dropped_cycles) {
214             debugWarning("(%p) Correcting timestamp for dropped cycles, discarding packet...\n", this);
215             m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
216             // we don't want this first sample to be written
217             return RAW1394_ISO_OK;
218         }
219        
220         if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) {
221             retval=RAW1394_ISO_OK;
222
223             // process all ports that should be handled on a per-packet base
224             // this is MIDI for AMDTP (due to the need of DBC)
225             if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) {
226                 debugWarning("Problem decoding Packet Ports\n");
227                 retval=RAW1394_ISO_DEFER;
228             }
229
230         } else {
231
232 //             debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",
233 //                  cycle, m_data_buffer->getFrameCounter(), m_handler->getPacketCount());
234
235             m_xruns++;
236
237             retval=RAW1394_ISO_DEFER;
238         }
239     }
240
241     return retval;
242 }
243
244 void AmdtpReceiveStreamProcessor::dumpInfo() {
245     StreamProcessor::dumpInfo();
246 }
247
248 bool AmdtpReceiveStreamProcessor::reset() {
249
250     debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
251
252     m_PeriodStat.reset();
253     m_PacketStat.reset();
254     m_WakeupStat.reset();
255
256     m_data_buffer->setTickOffset(0);
257
258     // reset all non-device specific stuff
259     // i.e. the iso stream and the associated ports
260     if(!StreamProcessor::reset()) {
261             debugFatal("Could not do base class reset\n");
262             return false;
263     }
264     return true;
265 }
266
267 bool AmdtpReceiveStreamProcessor::prepare() {
268
269     m_PeriodStat.setName("RCV PERIOD");
270     m_PacketStat.setName("RCV PACKET");
271     m_WakeupStat.setName("RCV WAKEUP");
272
273     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this);
274
275     // prepare all non-device specific stuff
276     // i.e. the iso stream and the associated ports
277     if(!StreamProcessor::prepare()) {
278         debugFatal("Could not prepare base class\n");
279         return false;
280     }
281
282     switch (m_manager->getNominalRate()) {
283     case 32000:
284         m_syt_interval = 8;
285         break;
286     case 44100:
287         m_syt_interval = 8;
288         break;
289     default:
290     case 48000:
291         m_syt_interval = 8;
292         break;
293     case 88200:
294         m_syt_interval = 16;
295         break;
296     case 96000:
297         m_syt_interval = 16;
298         break;
299     case 176400:
300         m_syt_interval = 32;
301         break;
302     case 192000:
303         m_syt_interval = 32;
304         break;
305     }
306
307     // prepare the framerate estimate
308     float ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_manager->getNominalRate());
309     m_ticks_per_frame=ticks_per_frame;
310
311     debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n",ticks_per_frame);
312
313     // initialize internal buffer
314     unsigned int ringbuffer_size_frames=m_manager->getNbBuffers() * m_manager->getPeriodSize();
315
316     assert(m_data_buffer);
317     m_data_buffer->setBufferSize(ringbuffer_size_frames * 2);
318     m_data_buffer->setEventSize(sizeof(quadlet_t));
319     m_data_buffer->setEventsPerFrame(m_dimension);
320
321     // the buffer is written every syt_interval
322     m_data_buffer->setUpdatePeriod(m_syt_interval);
323     m_data_buffer->setNominalRate(ticks_per_frame);
324
325     m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND);
326
327     m_data_buffer->prepare();
328
329     // set the parameters of ports we can:
330     // we want the audio ports to be period buffered,
331     // and the midi ports to be packet buffered
332     for ( PortVectorIterator it = m_Ports.begin();
333           it != m_Ports.end();
334           ++it )
335     {
336         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
337         if(!(*it)->setBufferSize(m_manager->getPeriodSize())) {
338             debugFatal("Could not set buffer size to %d\n",m_manager->getPeriodSize());
339             return false;
340         }
341
342         switch ((*it)->getPortType()) {
343             case Port::E_Audio:
344                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
345                     debugFatal("Could not set signal type to PeriodSignalling");
346                     return false;
347                 }
348                 // buffertype and datatype are dependant on the API
349                 debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");
350                 // buffertype and datatype are dependant on the API
351                 if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
352                     debugFatal("Could not set buffer type");
353                     return false;
354                 }
355                 if(!(*it)->useExternalBuffer(true)) {
356                     debugFatal("Could not set external buffer usage");
357                     return false;
358                 }
359                 if(!(*it)->setDataType(Port::E_Float)) {
360                     debugFatal("Could not set data type");
361                     return false;
362                 }
363                 break;
364             case Port::E_Midi:
365                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
366                     debugFatal("Could not set signal type to PacketSignalling");
367                     return false;
368                 }
369                 // buffertype and datatype are dependant on the API
370                 // buffertype and datatype are dependant on the API
371                 debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
372                 // buffertype and datatype are dependant on the API
373                 if(!(*it)->setBufferType(Port::E_RingBuffer)) {
374                     debugFatal("Could not set buffer type");
375                     return false;
376                 }
377                 if(!(*it)->setDataType(Port::E_MidiEvent)) {
378                     debugFatal("Could not set data type");
379                     return false;
380                 }
381                 break;
382             default:
383                 debugWarning("Unsupported port type specified\n");
384                 break;
385         }
386     }
387
388     // the API specific settings of the ports should already be set,
389     // as this is called from the processorManager->prepare()
390     // so we can init the ports
391     if(!initPorts()) {
392         debugFatal("Could not initialize ports!\n");
393         return false;
394     }
395
396     if(!preparePorts()) {
397         debugFatal("Could not initialize ports!\n");
398         return false;
399     }
400
401     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
402     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, DBS: %d, SYT: %d\n",
403              m_manager->getNominalRate(),m_dimension,m_syt_interval);
404     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
405              m_manager->getPeriodSize(), m_manager->getNbBuffers());
406     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
407              m_port,m_channel);
408
409     return true;
410
411 }
412
413 bool AmdtpReceiveStreamProcessor::prepareForStart() {
414     disable();
415     return true;
416 }
417
418 bool AmdtpReceiveStreamProcessor::prepareForStop() {
419     disable();
420     return true;
421 }
422
423 unsigned int
424 AmdtpReceiveStreamProcessor::getPacketsPerPeriod()
425 {
426     return (m_manager->getPeriodSize())/m_syt_interval;
427 }
428
429 bool AmdtpReceiveStreamProcessor::getFrames(unsigned int nbframes, int64_t ts) {
430     m_PeriodStat.mark(m_data_buffer->getBufferFill());
431
432 #ifdef DEBUG
433     uint64_t ts_head;
434     signed int fc;
435     int32_t lag_ticks;
436     float lag_frames;
437
438     // in order to sync up multiple received streams, we should
439     // use the ts parameter. It specifies the time of the block's
440     // first sample.
441    
442     ffado_timestamp_t ts_head_tmp;
443     m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc);
444     ts_head=(uint64_t)ts_head_tmp;
445     lag_ticks=diffTicks(ts, ts_head);
446     float rate=m_data_buffer->getRate();
447    
448     assert(rate!=0.0);
449    
450     lag_frames=(((float)lag_ticks)/rate);
451    
452     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): drifts %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
453                  this, lag_ticks, lag_frames,rate, ts, ts_head, fc);
454
455     if (lag_frames>=1.0) {
456         // the stream lags
457         debugWarning( "stream (%p): lags  with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
458                       this, lag_ticks, lag_frames,rate, ts, ts_head, fc);
459     } else if (lag_frames<=-1.0) {
460         // the stream leads
461         debugWarning( "stream (%p): leads with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
462                       this, lag_ticks, lag_frames,rate, ts, ts_head, fc);
463     }
464 #endif
465     // ask the buffer to process nbframes of frames
466     // using it's registered client's processReadBlock(),
467     // which should be ours
468     m_data_buffer->blockProcessReadFrames(nbframes);
469
470     return true;
471 }
472
473 bool AmdtpReceiveStreamProcessor::getFramesDry(unsigned int nbframes, int64_t ts) {
474     m_PeriodStat.mark(m_data_buffer->getBufferFill());
475     int frames_to_ditch=(int)(nbframes);
476     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): dry run %d frames (@ ts=%lld)\n",
477                  this, frames_to_ditch, ts);
478     char dummy[m_data_buffer->getBytesPerFrame()]; // one frame of garbage
479
480     while (frames_to_ditch--) {
481         m_data_buffer->readFrames(1, dummy);
482     }
483     return true;
484 }
485
486 /**
487  * \brief write received events to the stream ringbuffers.
488  */
489 bool AmdtpReceiveStreamProcessor::processReadBlock(char *data,
490                        unsigned int nevents, unsigned int offset)
491 {
492     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p)->processReadBlock(%u, %u)\n",this,nevents,offset);
493
494     bool no_problem=true;
495
496     for ( PortVectorIterator it = m_PeriodPorts.begin();
497           it != m_PeriodPorts.end();
498           ++it )
499     {
500
501         if((*it)->isDisabled()) {continue;};
502
503         //FIXME: make this into a static_cast when not DEBUG?
504
505         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
506         assert(pinfo); // this should not fail!!
507
508         switch(pinfo->getFormat()) {
509         case AmdtpPortInfo::E_MBLA:
510             if(decodeMBLAEventsToPort(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
511                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str());
512                 no_problem=false;
513             }
514             break;
515         case AmdtpPortInfo::E_SPDIF: // still unimplemented
516             break;
517     /* for this processor, midi is a packet based port
518         case AmdtpPortInfo::E_Midi:
519             break;*/
520         default: // ignore
521             break;
522         }
523     }
524     return no_problem;
525
526 }
527
528 /**
529  * @brief decode a packet for the packet-based ports
530  *
531  * @param data Packet data
532  * @param nevents number of events in data (including events of other ports & port types)
533  * @param dbc DataBlockCount value for this packet
534  * @return true if all successfull
535  */
536 bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
537 {
538     bool ok=true;
539
540     quadlet_t *target_event=NULL;
541     unsigned int j;
542
543     for ( PortVectorIterator it = m_PacketPorts.begin();
544           it != m_PacketPorts.end();
545           ++it )
546     {
547
548 #ifdef DEBUG
549         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
550         assert(pinfo); // this should not fail!!
551
552         // the only packet type of events for AMDTP is MIDI in mbla
553         assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi);
554 #endif
555         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it);
556
557         // we decode this directly (no function call) due to the high frequency
558         /* idea:
559         spec says: current_midi_port=(dbc+j)%8;
560         => if we start at (dbc+stream->location-1)%8,
561         we'll start at the right event for the midi port.
562         => if we increment j with 8, we stay at the right event.
563         */
564         // FIXME: as we know in advance how big a packet is (syt_interval) we can
565         //        predict how much loops will be present here
566         for(j = (dbc & 0x07)+mp->getLocation(); j < nevents; j += 8) {
567             target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition()));
568             quadlet_t sample_int=ntohl(*target_event);
569             // FIXME: this assumes that 2X and 3X speed isn't used,
570             // because only the 1X slot is put into the ringbuffer
571             if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) {
572                 sample_int=(sample_int >> 16) & 0x000000FF;
573                 if(!mp->writeEvent(&sample_int)) {
574                     debugWarning("Packet port events lost\n");
575                     ok=false;
576                 }
577             }
578         }
579
580     }
581
582     return ok;
583 }
584
585 int AmdtpReceiveStreamProcessor::decodeMBLAEventsToPort(AmdtpAudioPort *p, quadlet_t *data,
586                        unsigned int offset, unsigned int nevents)
587 {
588     unsigned int j=0;
589
590 //     printf("****************\n");
591 //     hexDumpQuadlets(data,m_dimension*4);
592 //     printf("****************\n");
593
594     quadlet_t *target_event;
595
596     target_event=(quadlet_t *)(data + p->getPosition());
597
598     switch(p->getDataType()) {
599         default:
600         case Port::E_Int24:
601             {
602                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
603
604                 assert(nevents + offset <= p->getBufferSize());
605
606                 buffer+=offset;
607
608                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
609                     *(buffer)=(ntohl((*target_event) ) & 0x00FFFFFF);
610                     buffer++;
611                     target_event+=m_dimension;
612                 }
613             }
614             break;
615         case Port::E_Float:
616             {
617                 const float multiplier = 1.0f / (float)(0x7FFFFF);
618                 float *buffer=(float *)(p->getBufferAddress());
619
620                 assert(nevents + offset <= p->getBufferSize());
621
622                 buffer+=offset;
623
624                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
625
626                     unsigned int v = ntohl(*target_event) & 0x00FFFFFF;
627                     // sign-extend highest bit of 24-bit int
628                     int tmp = (int)(v << 8) / 256;
629
630                     *buffer = tmp * multiplier;
631
632                     buffer++;
633                     target_event+=m_dimension;
634                 }
635             }
636             break;
637     }
638
639     return 0;
640 }
641
642 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.