root/branches/ppalmers-streaming/src/libstreaming/motu/MotuReceiveStreamProcessor.cpp

Revision 732, 13.0 kB (checked in by ppalmers, 14 years ago)

reorganize motu SP files to prepare for updated streaming implementation (disfunctional)

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 {}
48
49 unsigned int
50 AmdtpReceiveStreamProcessor::getNominalPacketsNeeded(unsigned int nframes)
51 {
52     unsigned int nominal_frames_per_second = m_manager->getNominalRate();
53     uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second;
54     uint64_t nominal_ticks = nominal_ticks_per_frame * nframes;
55     uint64_t nominal_packets = nominal_ticks / TICKS_PER_CYCLE;
56     return nominal_packets;
57 }
58
59 unsigned int
60 AmdtpReceiveStreamProcessor::getPacketsPerPeriod()
61 {
62     return getNominalPacketsNeeded(m_manager->getPeriodSize());
63 }
64
65 bool AmdtpReceiveStreamProcessor::prepareChild() {
66     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing (%p)...\n", this);
67
68     switch (m_manager->getNominalRate()) {
69         case 32000:
70         case 44100:
71         case 48000:
72             m_syt_interval = 8;
73             break;
74         case 88200:
75         case 96000:
76             m_syt_interval = 16;
77             break;
78         case 176400:
79         case 192000:
80             m_syt_interval = 32;
81             break;
82         default:
83             debugError("Unsupported rate: %d\n", m_manager->getNominalRate());
84             return false;
85     }
86
87     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
88     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d, DBS: %d, SYT: %d\n",
89              m_manager->getNominalRate(), m_dimension, m_syt_interval);
90     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
91              m_manager->getPeriodSize(), m_manager->getNbBuffers());
92     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
93              m_port,m_channel);
94
95     return true;
96 }
97
98
99 /**
100  * Processes packet header to extract timestamps and so on
101  * @param data
102  * @param length
103  * @param channel
104  * @param tag
105  * @param sy
106  * @param cycle
107  * @param dropped
108  * @return
109  */
110 enum StreamProcessor::eChildReturnValue
111 AmdtpReceiveStreamProcessor::processPacketHeader(unsigned char *data, unsigned int length,
112                   unsigned char channel, unsigned char tag, unsigned char sy,
113                   unsigned int cycle, unsigned int dropped)
114 {
115     struct iec61883_packet *packet = (struct iec61883_packet *) data;
116     assert(packet);
117     bool ok = (packet->syt != 0xFFFF) &&
118                   (packet->fdf != 0xFF) &&
119                   (packet->fmt == 0x10) &&
120                   (packet->dbs > 0) &&
121                   (length >= 2*sizeof(quadlet_t));
122     if(ok) {
123         uint64_t now = m_handler->getCycleTimer();
124         //=> convert the SYT to a full timestamp in ticks
125         m_last_timestamp = sytRecvToFullTicks((uint32_t)ntohs(packet->syt),
126                                               cycle, now);
127     }
128     return (ok ? eCRV_OK : eCRV_Invalid );
129 }
130
131 /**
132  * extract the data from the packet
133  * @pre the IEC61883 packet is valid according to isValidPacket
134  * @param data
135  * @param length
136  * @param channel
137  * @param tag
138  * @param sy
139  * @param cycle
140  * @param dropped
141  * @return
142  */
143 enum StreamProcessor::eChildReturnValue
144 AmdtpReceiveStreamProcessor::processPacketData(unsigned char *data, unsigned int length,
145                   unsigned char channel, unsigned char tag, unsigned char sy,
146                   unsigned int cycle, unsigned int dropped_cycles) {
147     struct iec61883_packet *packet = (struct iec61883_packet *) data;
148     assert(packet);
149
150     unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
151
152     // we have to keep in mind that there are also
153     // some packets buffered by the ISO layer,
154     // at most x=m_handler->getWakeupInterval()
155     // these contain at most x*syt_interval
156     // frames, meaning that we might receive
157     // this packet x*syt_interval*ticks_per_frame
158     // later than expected (the real receive time)
159     #ifdef DEBUG
160     if(isRunning()) {
161         debugOutput(DEBUG_LEVEL_VERY_VERBOSE,"STMP: %lluticks | buff=%d, syt_interval=%d, tpf=%f\n",
162             m_last_timestamp, m_handler->getWakeupInterval(), m_syt_interval, getTicksPerFrame());
163     }
164     #endif
165
166     if(m_data_buffer->writeFrames(nevents, (char *)(data+8), m_last_timestamp)) {
167         // process all ports that should be handled on a per-packet base
168         // this is MIDI for AMDTP (due to the need of DBC)
169         if(isRunning()) {
170             if (!decodePacketPorts((quadlet_t *)(data+8), nevents, packet->dbc)) {
171                 debugWarning("Problem decoding Packet Ports\n");
172             }
173         }
174         return eCRV_OK;
175     } else {
176         return eCRV_XRun;
177     }
178 }
179
180 /***********************************************
181  * Encoding/Decoding API                       *
182  ***********************************************/
183 /**
184  * @brief write received events to the stream ringbuffers.
185  */
186 bool AmdtpReceiveStreamProcessor::processReadBlock(char *data,
187                        unsigned int nevents, unsigned int offset)
188 {
189     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p)->processReadBlock(%u, %u)\n",this,nevents,offset);
190
191     bool no_problem=true;
192
193     for ( PortVectorIterator it = m_PeriodPorts.begin();
194           it != m_PeriodPorts.end();
195           ++it )
196     {
197         if((*it)->isDisabled()) {continue;};
198
199         //FIXME: make this into a static_cast when not DEBUG?
200
201         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
202         assert(pinfo); // this should not fail!!
203
204         switch(pinfo->getFormat()) {
205         case AmdtpPortInfo::E_MBLA:
206             if(decodeMBLAEventsToPort(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
207                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str());
208                 no_problem=false;
209             }
210             break;
211         case AmdtpPortInfo::E_SPDIF: // still unimplemented
212             break;
213     /* for this processor, midi is a packet based port
214         case AmdtpPortInfo::E_Midi:
215             break;*/
216         default: // ignore
217             break;
218         }
219     }
220     return no_problem;
221 }
222
223 /**
224  * @brief write silence events to the stream ringbuffers.
225  */
226 bool AmdtpReceiveStreamProcessor::provideSilenceBlock(unsigned int nevents, unsigned int offset)
227 {
228     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "(%p)->proviceSilenceBlock(%u, %u)\n", this, nevents, offset);
229
230     bool no_problem=true;
231
232     for ( PortVectorIterator it = m_PeriodPorts.begin();
233           it != m_PeriodPorts.end();
234           ++it )
235     {
236         if((*it)->isDisabled()) {continue;};
237         //FIXME: make this into a static_cast when not DEBUG?
238         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
239         assert(pinfo); // this should not fail!!
240
241         switch(pinfo->getFormat()) {
242         case AmdtpPortInfo::E_MBLA:
243             if(provideSilenceToPort(static_cast<AmdtpAudioPort *>(*it), offset, nevents)) {
244                 debugWarning("Could not put silence into to port %s",(*it)->getName().c_str());
245                 no_problem=false;
246             }
247             break;
248         case AmdtpPortInfo::E_SPDIF: // still unimplemented
249             break;
250     /* for this processor, midi is a packet based port
251         case AmdtpPortInfo::E_Midi:
252             break;*/
253         default: // ignore
254             break;
255         }
256     }
257     return no_problem;
258 }
259
260 /**
261  * @brief decode a packet for the packet-based ports
262  *
263  * @param data Packet data
264  * @param nevents number of events in data (including events of other ports & port types)
265  * @param dbc DataBlockCount value for this packet
266  * @return true if all successfull
267  */
268 bool AmdtpReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
269 {
270     bool ok=true;
271
272     quadlet_t *target_event=NULL;
273     unsigned int j;
274
275     for ( PortVectorIterator it = m_PacketPorts.begin();
276           it != m_PacketPorts.end();
277           ++it )
278     {
279
280 #ifdef DEBUG
281         AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it);
282         assert(pinfo); // this should not fail!!
283
284         // the only packet type of events for AMDTP is MIDI in mbla
285         assert(pinfo->getFormat()==AmdtpPortInfo::E_Midi);
286 #endif
287         AmdtpMidiPort *mp=static_cast<AmdtpMidiPort *>(*it);
288
289         // we decode this directly (no function call) due to the high frequency
290         /* idea:
291         spec says: current_midi_port=(dbc+j)%8;
292         => if we start at (dbc+stream->location-1)%8,
293         we'll start at the right event for the midi port.
294         => if we increment j with 8, we stay at the right event.
295         */
296         // FIXME: as we know in advance how big a packet is (syt_interval) we can
297         //        predict how much loops will be present here
298         for(j = (dbc & 0x07)+mp->getLocation(); j < nevents; j += 8) {
299             target_event=(quadlet_t *)(data + ((j * m_dimension) + mp->getPosition()));
300             quadlet_t sample_int=ntohl(*target_event);
301             // FIXME: this assumes that 2X and 3X speed isn't used,
302             // because only the 1X slot is put into the ringbuffer
303             if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) {
304                 sample_int=(sample_int >> 16) & 0x000000FF;
305                 if(!mp->writeEvent(&sample_int)) {
306                     debugWarning("Packet port events lost\n");
307                     ok=false;
308                 }
309             }
310         }
311
312     }
313
314     return ok;
315 }
316
317 int
318 AmdtpReceiveStreamProcessor::decodeMBLAEventsToPort(
319                        AmdtpAudioPort *p, quadlet_t *data,
320                        unsigned int offset, unsigned int nevents)
321 {
322     unsigned int j=0;
323     quadlet_t *target_event;
324
325     target_event=(quadlet_t *)(data + p->getPosition());
326
327     switch(p->getDataType()) {
328         default:
329         case Port::E_Int24:
330             {
331                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
332
333                 assert(nevents + offset <= p->getBufferSize());
334
335                 buffer+=offset;
336
337                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
338                     *(buffer)=(ntohl((*target_event) ) & 0x00FFFFFF);
339                     buffer++;
340                     target_event+=m_dimension;
341                 }
342             }
343             break;
344         case Port::E_Float:
345             {
346                 const float multiplier = 1.0f / (float)(0x7FFFFF);
347                 float *buffer=(float *)(p->getBufferAddress());
348
349                 assert(nevents + offset <= p->getBufferSize());
350
351                 buffer+=offset;
352
353                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
354
355                     unsigned int v = ntohl(*target_event) & 0x00FFFFFF;
356                     // sign-extend highest bit of 24-bit int
357                     int tmp = (int)(v << 8) / 256;
358
359                     *buffer = tmp * multiplier;
360
361                     buffer++;
362                     target_event+=m_dimension;
363                 }
364             }
365             break;
366     }
367
368     return 0;
369 }
370
371 int
372 AmdtpReceiveStreamProcessor::provideSilenceToPort(
373                        AmdtpAudioPort *p, unsigned int offset, unsigned int nevents)
374 {
375     unsigned int j=0;
376     switch(p->getDataType()) {
377         default:
378         case Port::E_Int24:
379             {
380                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
381                 assert(nevents + offset <= p->getBufferSize());
382                 buffer+=offset;
383
384                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
385                     *(buffer)=0;
386                     buffer++;
387                 }
388             }
389             break;
390         case Port::E_Float:
391             {
392                 float *buffer=(float *)(p->getBufferAddress());
393                 assert(nevents + offset <= p->getBufferSize());
394                 buffer+=offset;
395
396                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
397                     *buffer = 0.0;
398                     buffer++;
399                 }
400             }
401             break;
402     }
403     return 0;
404 }
405
406 } // end of namespace Streaming
Note: See TracBrowser for help on using the browser.