root/branches/libffado-2.0/src/libstreaming/amdtp/AmdtpReceiveStreamProcessor.cpp

Revision 1524, 16.5 kB (checked in by ppalmers, 15 years ago)

- Fix handling of MIDI 2x and 3x mode
- Introduce support for driver parameters in the config file
- add command rate control for the saffire devices to reduce

the issues with mixer actions messing up audio.


Line 
1 /*
2  * Copyright (C) 2005-2008 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 program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23 #include "config.h"
24
25 #include "AmdtpReceiveStreamProcessor.h"
26 #include "AmdtpPort.h"
27 #include "../StreamProcessorManager.h"
28 #include "devicemanager.h"
29
30 #include "libieee1394/ieee1394service.h"
31 #include "libieee1394/IsoHandlerManager.h"
32 #include "libieee1394/cycletimer.h"
33
34 #include "libutil/ByteSwap.h"
35 #include <assert.h>
36 #include "libutil/SystemTimeSource.h"
37
38 namespace Streaming {
39
40 /* --------------------- RECEIVE ----------------------- */
41
42 AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(FFADODevice &parent, int dimension)
43     : StreamProcessor(parent, ePT_Receive)
44     , m_dimension( dimension )
45     , m_nb_audio_ports( 0 )
46     , m_nb_midi_ports( 0 )
47
48 {}
49
50 unsigned int
51 AmdtpReceiveStreamProcessor::getSytInterval() {
52     switch (m_StreamProcessorManager.getNominalRate()) {
53         case 32000:
54         case 44100:
55         case 48000:
56             return 8;
57         case 88200:
58         case 96000:
59             return 16;
60         case 176400:
61         case 192000:
62             return 32;
63         default:
64             debugError("Unsupported rate: %d\n", m_StreamProcessorManager.getNominalRate());
65             return 0;
66     }
67 }
68
69 bool AmdtpReceiveStreamProcessor::prepareChild() {
70     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this);
71     m_syt_interval = getSytInterval();
72
73     if (!initPortCache()) {
74         debugError("Could not init port cache\n");
75         return false;
76     }
77
78     return true;
79 }
80
81
82 /**
83  * Processes packet header to extract timestamps and so on
84  * @param data
85  * @param length
86  * @param channel
87  * @param tag
88  * @param sy
89  * @param pkt_ctr CTR value when packet was received
90  * @return
91  */
92 enum StreamProcessor::eChildReturnValue
93 AmdtpReceiveStreamProcessor::processPacketHeader(unsigned char *data, unsigned int length,
94                                                  unsigned char tag, unsigned char sy,
95                                                  uint32_t pkt_ctr)
96 {
97     struct iec61883_packet *packet = (struct iec61883_packet *) data;
98     assert(packet);
99     bool ok = (packet->syt != 0xFFFF) &&
100               (packet->fdf != 0xFF) &&
101               (packet->fmt == 0x10) &&
102               (packet->dbs > 0) &&
103               (length >= 2*sizeof(quadlet_t));
104     if(ok) {
105         m_last_timestamp = sytRecvToFullTicks2((uint32_t)CondSwapFromBus16(packet->syt), pkt_ctr);
106         //#ifdef DEBUG
107         #if 0
108         uint32_t now = m_1394service.getCycleTimer();
109
110         //=> convert the SYT to a full timestamp in ticks
111         uint64_t old_last_timestamp = sytRecvToFullTicks((uint32_t)CondSwapFromBus16(packet->syt),
112                                               CYCLE_TIMER_GET_CYCLES(pkt_ctr), now);
113         if(m_last_timestamp != old_last_timestamp) {
114             debugWarning("discepancy between timestamp calculations\n");
115         }
116         #endif
117     }
118     return (ok ? eCRV_OK : eCRV_Invalid );
119 }
120
121 /**
122  * extract the data from the packet
123  * @pre the IEC61883 packet is valid according to isValidPacket
124  * @param data
125  * @param length
126  * @param channel
127  * @param tag
128  * @param sy
129  * @param pkt_ctr
130  * @return
131  */
132 enum StreamProcessor::eChildReturnValue
133 AmdtpReceiveStreamProcessor::processPacketData(unsigned char *data, unsigned int length) {
134     struct iec61883_packet *packet = (struct iec61883_packet *) data;
135     assert(packet);
136
137     unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
138
139     // we have to keep in mind that there are also
140     // some packets buffered by the ISO layer,
141     // at most x=m_handler->getWakeupInterval()
142     // these contain at most x*syt_interval
143     // frames, meaning that we might receive
144     // this packet x*syt_interval*ticks_per_frame
145     // later than expected (the real receive time)
146     #ifdef DEBUG
147     static int64_t last_t = Util::SystemTimeSource::getCurrentTime();
148     int64_t now_t = Util::SystemTimeSource::getCurrentTime();
149     if(isRunning()) {
150         debugOutputExtreme(DEBUG_LEVEL_VERY_VERBOSE,
151                            "STMP: %lluticks | syt_interval=%d, tpf=%f\n",
152                            m_last_timestamp, m_syt_interval, getTicksPerFrame());
153 /*        debugOutput(DEBUG_LEVEL_NORMAL,
154                            "STMP: %12llu ticks | delta_t: %5lld | bufferfill: %5d\n",
155                            m_last_timestamp, now_t-last_t, m_data_buffer->getBufferFill());*/
156     }
157     last_t = now_t;
158
159     // check whether nevents is a multiple of 8.
160     if (nevents & 0x7) {
161         debugError("Invalid nevents value for AMDTP (%u)\n", nevents);
162     }
163     #endif
164
165     if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) {
166         return eCRV_OK;
167     } else {
168         return eCRV_XRun;
169     }
170 }
171
172 /***********************************************
173  * Encoding/Decoding API                       *
174  ***********************************************/
175 /**
176  * @brief write received events to the stream ringbuffers.
177  */
178 bool AmdtpReceiveStreamProcessor::processReadBlock(char *data,
179                        unsigned int nevents, unsigned int offset)
180 {
181     debugOutputExtreme( DEBUG_LEVEL_VERY_VERBOSE,
182                         "(%p)->processReadBlock(%u, %u)\n",
183                         this, nevents, offset);
184
185     // update the variable parts of the cache
186     updatePortCache();
187
188     // decode audio data
189     switch(m_StreamProcessorManager.getAudioDataType()) {
190         case StreamProcessorManager::eADT_Int24:
191             decodeAudioPortsInt24((quadlet_t *)data, offset, nevents);
192             break;
193         case StreamProcessorManager::eADT_Float:
194             decodeAudioPortsFloat((quadlet_t *)data, offset, nevents);
195             break;
196     }
197
198     // do midi ports
199     decodeMidiPorts((quadlet_t *)data, offset, nevents);
200     return true;
201 }
202
203 //#ifdef __SSE2__
204 #if 0 // SSE code is not ready yet
205 #include <emmintrin.h>
206 #warning SSE2 build
207
208 /**
209  * @brief demux events to all audio ports (int24)
210  * @param data
211  * @param offset
212  * @param nevents
213  */
214 void
215 AmdtpReceiveStreamProcessor::decodeAudioPortsInt24(quadlet_t *data,
216                                                     unsigned int offset,
217                                                     unsigned int nevents)
218 {
219     unsigned int j;
220     quadlet_t *target_event;
221     unsigned int i;
222
223     for (i = 0; i < m_nb_audio_ports; i++) {
224         struct _MBLA_port_cache &p = m_audio_ports.at(i);
225         target_event = (quadlet_t *)(data + i);
226         assert(nevents + offset <= p.buffer_size );
227
228         if(p.buffer && p.enabled) {
229             quadlet_t *buffer = (quadlet_t *)(p.buffer);
230             buffer += offset;
231
232             for(j = 0; j < nevents; j += 1) {
233                 *(buffer)=(CondSwapFromBus32((*target_event) ) & 0x00FFFFFF);
234                 buffer++;
235                 target_event+=m_dimension;
236             }
237         }
238     }
239 }
240
241 /**
242  * @brief demux events to all audio ports (float)
243  * @param data
244  * @param offset
245  * @param nevents
246  */
247 void
248 AmdtpReceiveStreamProcessor::decodeAudioPortsFloat(quadlet_t *data,
249                                                     unsigned int offset,
250                                                     unsigned int nevents)
251 {
252     unsigned int j;
253     quadlet_t *target_event;
254     unsigned int i;
255     const float multiplier = 1.0f / (float)(0x7FFFFF);
256
257     for (i = 0; i < m_nb_audio_ports; i++) {
258         struct _MBLA_port_cache &p = m_audio_ports.at(i);
259         target_event = (quadlet_t *)(data + i);
260         assert(nevents + offset <= p.buffer_size );
261
262         if(p.buffer && p.enabled) {
263             float *buffer = (float *)(p.buffer);
264             buffer += offset;
265
266             for(j = 0; j < nevents; j += 1) {
267                 unsigned int v = CondSwapFromBus32(*target_event) & 0x00FFFFFF;
268                 // sign-extend highest bit of 24-bit int
269                 int tmp = (int)(v << 8) / 256;
270                 *buffer = tmp * multiplier;
271                 buffer++;
272                 target_event+=m_dimension;
273             }
274         }
275     }
276 }
277
278 #else
279 /**
280  * @brief demux events to all audio ports (int24)
281  * @param data
282  * @param offset
283  * @param nevents
284  */
285 void
286 AmdtpReceiveStreamProcessor::decodeAudioPortsInt24(quadlet_t *data,
287                                                     unsigned int offset,
288                                                     unsigned int nevents)
289 {
290     unsigned int j;
291     quadlet_t *target_event;
292     unsigned int i;
293
294     for (i = 0; i < m_nb_audio_ports; i++) {
295         struct _MBLA_port_cache &p = m_audio_ports.at(i);
296         target_event = (quadlet_t *)(data + i);
297         assert(nevents + offset <= p.buffer_size );
298
299         if(p.buffer && p.enabled) {
300             quadlet_t *buffer = (quadlet_t *)(p.buffer);
301             buffer += offset;
302
303             for(j = 0; j < nevents; j += 1) {
304                 *(buffer)=(CondSwapFromBus32((*target_event) ) & 0x00FFFFFF);
305                 buffer++;
306                 target_event+=m_dimension;
307             }
308         }
309     }
310 }
311
312 /**
313  * @brief demux events to all audio ports (float)
314  * @param data
315  * @param offset
316  * @param nevents
317  */
318 void
319 AmdtpReceiveStreamProcessor::decodeAudioPortsFloat(quadlet_t *data,
320                                                     unsigned int offset,
321                                                     unsigned int nevents)
322 {
323     unsigned int j;
324     quadlet_t *target_event;
325     unsigned int i;
326     const float multiplier = 1.0f / (float)(0x7FFFFF);
327
328     for (i = 0; i < m_nb_audio_ports; i++) {
329         struct _MBLA_port_cache &p = m_audio_ports.at(i);
330         target_event = (quadlet_t *)(data + i);
331         assert(nevents + offset <= p.buffer_size );
332
333         if(p.buffer && p.enabled) {
334             float *buffer = (float *)(p.buffer);
335             buffer += offset;
336
337             for(j = 0; j < nevents; j += 1) {
338                 unsigned int v = CondSwapFromBus32(*target_event) & 0x00FFFFFF;
339                 // sign-extend highest bit of 24-bit int
340                 int tmp = (int)(v << 8) / 256;
341                 *buffer = tmp * multiplier;
342                 buffer++;
343                 target_event+=m_dimension;
344             }
345         }
346     }
347 }
348
349 #endif
350
351 /**
352  * @brief decode all midi ports in the cache from events
353  * @param data
354  * @param offset
355  * @param nevents
356  */
357 void
358 AmdtpReceiveStreamProcessor::decodeMidiPorts(quadlet_t *data,
359                                               unsigned int offset,
360                                               unsigned int nevents)
361 {
362     quadlet_t *target_event;
363     quadlet_t sample_int;
364     unsigned int i,j;
365
366     for (i = 0; i < m_nb_midi_ports; i++) {
367         struct _MIDI_port_cache &p = m_midi_ports.at(i);
368         if (p.buffer && p.enabled) {
369             uint32_t *buffer = (quadlet_t *)(p.buffer);
370             buffer += offset;
371             for (j = p.location;j < nevents; j += 8) {
372                 target_event = (quadlet_t *) (data + ((j * m_dimension) + p.position));
373                 sample_int = CondSwapFromBus32(*target_event);
374
375                 // FIXME: this assumes that 2X and 3X speed isn't used,
376                 // because only the 1X slot is put into the ringbuffer
377                 if(IEC61883_AM824_HAS_LABEL(sample_int, IEC61883_AM824_LABEL_MIDI_1X)) {
378                     sample_int=(sample_int >> 16) & 0x000000FF;
379                     sample_int |= 0x01000000; // flag that there is a midi event present
380                     *buffer = sample_int;
381                 } else if(IEC61883_AM824_HAS_LABEL(sample_int, IEC61883_AM824_LABEL_MIDI_2X)
382                        || IEC61883_AM824_HAS_LABEL(sample_int, IEC61883_AM824_LABEL_MIDI_3X) ) {
383                     debugOutput(DEBUG_LEVEL_VERBOSE, "Midi mode %X not supported.\n", IEC61883_AM824_GET_LABEL(sample_int));
384                 } else {
385                     // make sure no event is received
386                     *buffer = 0;
387                 }
388                 buffer+=8;
389             }
390         }
391     }
392 }
393
394 bool
395 AmdtpReceiveStreamProcessor::initPortCache() {
396     // make use of the fact that audio ports are the first ports in
397     // the cluster as per AMDTP. so we can sort the ports by position
398     // and have very efficient lookups:
399     // m_float_ports.at(i).buffer -> audio stream i buffer
400     // for midi ports we simply cache all port info since they are (usually) not
401     // that numerous
402     m_nb_audio_ports = 0;
403     m_audio_ports.clear();
404    
405     m_nb_midi_ports = 0;
406     m_midi_ports.clear();
407    
408     for(PortVectorIterator it = m_Ports.begin();
409         it != m_Ports.end();
410         ++it )
411     {
412         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
413         assert(pinfo); // this should not fail!!
414
415         switch( pinfo->getFormat() )
416         {
417             case AmdtpPortInfo::E_MBLA:
418                 m_nb_audio_ports++;
419                 break;
420             case AmdtpPortInfo::E_SPDIF: // still unimplemented
421                 break;
422             case AmdtpPortInfo::E_Midi:
423                 m_nb_midi_ports++;
424                 break;
425             default: // ignore
426                 break;
427         }
428     }
429
430     unsigned int idx;
431     for (idx = 0; idx < m_nb_audio_ports; idx++) {
432         for(PortVectorIterator it = m_Ports.begin();
433             it != m_Ports.end();
434             ++it )
435         {
436             AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
437             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
438                         "idx %u: looking at port %s at position %u\n",
439                         idx, (*it)->getName().c_str(), pinfo->getPosition());
440             if(pinfo->getPosition() == idx) {
441                 struct _MBLA_port_cache p;
442                 p.port = dynamic_cast<AmdtpAudioPort *>(*it);
443                 if(p.port == NULL) {
444                     debugError("Port is not an AmdtpAudioPort!\n");
445                     return false;
446                 }
447                 p.buffer = NULL; // to be filled by updatePortCache
448                 #ifdef DEBUG
449                 p.buffer_size = (*it)->getBufferSize();
450                 #endif
451
452                 m_audio_ports.push_back(p);
453                 debugOutput(DEBUG_LEVEL_VERBOSE,
454                             "Cached port %s at position %u\n",
455                             p.port->getName().c_str(), idx);
456                 goto next_index;
457             }
458         }
459         debugError("No MBLA port found for position %d\n", idx);
460         return false;
461 next_index:
462         continue;
463     }
464
465     for(PortVectorIterator it = m_Ports.begin();
466         it != m_Ports.end();
467         ++it )
468     {
469         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
470         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
471                     "idx %u: looking at port %s at position %u, location %u\n",
472                     idx, (*it)->getName().c_str(), pinfo->getPosition(), pinfo->getLocation());
473         if ((*it)->getPortType() == Port::E_Midi) {
474             struct _MIDI_port_cache p;
475             p.port = dynamic_cast<AmdtpMidiPort *>(*it);
476             if(p.port == NULL) {
477                 debugError("Port is not an AmdtpMidiPort!\n");
478                 return false;
479             }
480             p.position = pinfo->getPosition();
481             p.location = pinfo->getLocation();
482             p.buffer = NULL; // to be filled by updatePortCache
483             #ifdef DEBUG
484             p.buffer_size = (*it)->getBufferSize();
485             #endif
486
487             m_midi_ports.push_back(p);
488             debugOutput(DEBUG_LEVEL_VERBOSE,
489                         "Cached port %s at position %u, location %u\n",
490                         p.port->getName().c_str(), p.position, p.location);
491         }
492     }
493
494     return true;
495 }
496
497 void
498 AmdtpReceiveStreamProcessor::updatePortCache() {
499     unsigned int idx;
500     for (idx = 0; idx < m_nb_audio_ports; idx++) {
501         struct _MBLA_port_cache& p = m_audio_ports.at(idx);
502         AmdtpAudioPort *port = p.port;
503         p.buffer = port->getBufferAddress();
504         p.enabled = !port->isDisabled();
505     }
506     for (idx = 0; idx < m_nb_midi_ports; idx++) {
507         struct _MIDI_port_cache& p = m_midi_ports.at(idx);
508         AmdtpMidiPort *port = p.port;
509         p.buffer = port->getBufferAddress();
510         p.enabled = !port->isDisabled();
511     }
512 }
513
514 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.