Changeset 815

Show
Ignore:
Timestamp:
01/06/08 03:15:01 (13 years ago)
Author:
ppalmers
Message:

- AMDTP transmit port caching for better performance
- less debug output in critical path

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/api-cleanup/src/libieee1394/IsoHandler.cpp

    r807 r815  
    174174IsoHandler::waitForClient() 
    175175{ 
    176     debugOutput(DEBUG_LEVEL_VERBOSE, "waiting...\n"); 
     176    //debugOutput(DEBUG_LEVEL_VERBOSE, "waiting...\n"); 
    177177    if(m_Client) { 
    178178        bool result = m_Client->waitForSignal(); 
    179         debugOutput(DEBUG_LEVEL_VERBOSE, " returns %d\n", result); 
     179        //debugOutput(DEBUG_LEVEL_VERBOSE, " returns %d\n", result); 
    180180        return result; 
    181181    } else { 
     
    188188IsoHandler::tryWaitForClient() 
    189189{ 
    190     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "waiting...\n"); 
     190    //debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "waiting...\n"); 
    191191    if(m_Client) { 
    192192        bool result = m_Client->tryWaitForSignal(); 
    193         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result); 
     193        //debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " returns %d\n", result); 
    194194        return result; 
    195195    } else { 
     
    202202IsoHandler::Execute() 
    203203{ 
    204     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p: Execute thread...\n", this); 
     204    //debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p: Execute thread...\n", this); 
    205205 
    206206    // bypass if not running 
     
    214214    // wait for the availability of frames in the client 
    215215    // (blocking for transmit handlers) 
    216 #ifdef DEBUG 
     216 
     217#if 0 //#ifdef DEBUG 
    217218    if (getType() == eHT_Transmit) { 
    218219        debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) Waiting for Client to signal frame availability...\n", this); 
     
    256257        return true; 
    257258#else 
    258         // iterate blocks if no 1394 data is available 
     259        // iterate() is blocking if no 1394 data is available 
    259260        // so poll'ing is not really necessary 
    260          
    261261        bool result = true; 
    262262        while(result && m_Client->canProcessPackets()) { 
    263263            result = iterate(); 
    264             debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Iterate returned: %d\n", 
    265                         this, (m_type==eHT_Receive?"Receive":"Transmit"), result); 
     264            //debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Iterate returned: %d\n", 
     265            //            this, (m_type==eHT_Receive?"Receive":"Transmit"), result); 
    266266        } 
    267267        return result; 
     
    275275bool 
    276276IsoHandler::iterate() { 
    277     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Iterating ISO handler\n",  
    278                 this, (m_type==eHT_Receive?"Receive":"Transmit")); 
     277    //debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) Iterating ISO handler\n",  
     278    //            this, (m_type==eHT_Receive?"Receive":"Transmit")); 
    279279    if(m_State == E_Running) { 
    280280#if ISOHANDLER_FLUSH_BEFORE_ITERATE 
  • branches/api-cleanup/src/libstreaming/amdtp/AmdtpPortInfo.h

    r742 r815  
    6060 
    6161 
    62     int getLocation()     {return m_location;}; 
    63     int getPosition()     {return m_position;}; 
     62    unsigned int getLocation()     {return m_location;}; 
     63    unsigned int getPosition()     {return m_position;}; 
    6464    enum E_Formats getFormat()       {return m_format;}; 
    6565 
    6666protected: 
    67     int m_position; 
    68     int m_location; 
     67    unsigned int m_position; 
     68    unsigned int m_location; 
    6969    enum E_Formats m_format; 
    7070 
  • branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

    r812 r815  
    3737#include <assert.h> 
    3838 
     39#define AMDTP_FLOAT_MULTIPLIER 2147483392.0 
     40 
    3941namespace Streaming 
    4042{ 
     
    4547        , m_dimension( dimension ) 
    4648        , m_dbc( 0 ) 
     49        , m_nb_audio_ports( 0 ) 
     50        , m_nb_midi_ports( 0 ) 
    4751{} 
    4852 
     
    388392        m_syt_interval ); 
    389393 
     394    if (!initPortCache()) { 
     395        debugError("Could not init port cache\n"); 
     396        return false; 
     397    } 
     398 
    390399    return true; 
    391400} 
     
    398407{ 
    399408    bool no_problem = true; 
    400  
    401     for ( PortVectorIterator it = m_Ports.begin(); 
    402           it != m_Ports.end(); 
    403           ++it ) 
    404     { 
    405         if ( (*it)->isDisabled() ) { continue; }; 
    406  
    407         //FIXME: make this into a static_cast when not DEBUG? 
    408         AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); 
    409         assert ( pinfo ); // this should not fail!! 
    410  
    411         switch( pinfo->getFormat() ) 
    412         { 
    413             case AmdtpPortInfo::E_MBLA: 
    414                 if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
    415                 { 
    416                     debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); 
    417                     no_problem = false; 
    418                 } 
    419                 break; 
    420             case AmdtpPortInfo::E_SPDIF: // still unimplemented 
    421                 break; 
    422             case AmdtpPortInfo::E_Midi: 
    423                 if( encodePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
    424                 { 
    425                     debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() ); 
    426                     no_problem = false; 
    427                 } 
    428                 break; 
    429             default: // ignore 
    430                 break; 
    431         } 
    432     } 
     409    updatePortCache(); 
     410 
     411    if(!encodeAudioPorts((quadlet_t *)data, offset, nevents)) { 
     412        debugError("Could not encode audio ports\n"); 
     413        return false; 
     414    } 
     415 
     416//     for ( PortVectorIterator it = m_Ports.begin(); 
     417//           it != m_Ports.end(); 
     418//           ++it ) 
     419//     { 
     420//         if ( (*it)->isDisabled() ) { continue; }; 
     421//  
     422//         //FIXME: make this into a static_cast when not DEBUG? 
     423//         AmdtpPortInfo *pinfo = dynamic_cast<AmdtpPortInfo *> ( *it ); 
     424//         assert ( pinfo ); // this should not fail!! 
     425//  
     426//         switch( pinfo->getFormat() ) 
     427//         { 
     428//             case AmdtpPortInfo::E_MBLA: 
     429//                 if( encodePortToMBLAEvents(static_cast<AmdtpAudioPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
     430//                 { 
     431//                     debugWarning ( "Could not encode port %s to MBLA events", (*it)->getName().c_str() ); 
     432//                     no_problem = false; 
     433//                 } 
     434//                 break; 
     435//             case AmdtpPortInfo::E_SPDIF: // still unimplemented 
     436//                 break; 
     437//             case AmdtpPortInfo::E_Midi: 
     438//                 if( encodePortToMidiEvents(static_cast<AmdtpMidiPort *>(*it), (quadlet_t *)data, offset, nevents) ) 
     439//                 { 
     440//                     debugWarning ( "Could not encode port %s to Midi events", (*it)->getName().c_str() ); 
     441//                     no_problem = false; 
     442//                 } 
     443//                 break; 
     444//             default: // ignore 
     445//                 break; 
     446//         } 
     447//     } 
    433448    return no_problem; 
    434449} 
     
    472487} 
    473488 
    474 #if USE_SSE 
    475 #error Broken 
    476 typedef float v4sf __attribute__ ((vector_size (16))); 
    477 typedef int v4si __attribute__ ((vector_size (16))); 
    478 typedef int v2si __attribute__ ((vector_size (8))); 
    479  
    480489int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    481490        unsigned int offset, unsigned int nevents ) 
    482491{ 
    483     static const float sse_multiplier[4] __attribute__((aligned(16))) = { 
    484         (float)(0x7FFFFF00), 
    485         (float)(0x7FFFFF00), 
    486         (float)(0x7FFFFF00), 
    487         (float)(0x7FFFFF00) 
    488     }; 
    489  
    490     static const int sse_mask[4] __attribute__((aligned(16))) = { 
    491         0x40000000,  0x40000000,  0x40000000,  0x40000000 
    492     }; 
    493  
    494     unsigned int out[4]; 
    495  
    496492    unsigned int j=0; 
    497     unsigned int read=0; 
    498493 
    499494    quadlet_t *target_event; 
     
    524519        case Port::E_Float: 
    525520        { 
    526             const float multiplier = ( float ) ( 0x7FFFFF00 ); 
    527521            float *buffer= ( float * ) ( p->getBufferAddress() ); 
    528  
    529             assert ( nevents + offset <= p->getBufferSize() ); 
    530  
    531             buffer+=offset; 
    532  
    533             j=0; 
    534             if(read>3) { 
    535                 for (j = 0; j < read-3; j += 4) { 
    536                     asm("movups %[floatbuff], %%xmm0\n\t" 
    537                             "mulps %[ssemult], %%xmm0\n\t" 
    538                             "cvttps2pi %%xmm0, %[out1]\n\t" 
    539                             "movhlps %%xmm0, %%xmm0\n\t" 
    540                             "psrld $8, %[out1]\n\t" 
    541                             "cvttps2pi %%xmm0, %[out2]\n\t" 
    542                             "por %[mmxmask], %[out1]\n\t" 
    543                             "psrld $8, %[out2]\n\t" 
    544                             "por %[mmxmask], %[out2]\n\t" 
    545                         : [out1] "=&y" (*(v2si*)&out[0]), 
    546                     [out2] "=&y" (*(v2si*)&out[2]) 
    547                         : [floatbuff] "m" (*(v4sf*)buffer), 
    548                     [ssemult] "x" (*(v4sf*)sse_multiplier), 
    549                     [mmxmask] "y" (*(v2si*)sse_mask) 
    550                         : "xmm0"); 
    551                     buffer += 4; 
    552                     *target_event = htonl(out[0]); 
    553                     target_event += m_dimension; 
    554                     *target_event = htonl(out[1]); 
    555                     target_event += m_dimension; 
    556                     *target_event = htonl(out[2]); 
    557                     target_event += m_dimension; 
    558                     *target_event = htonl(out[3]); 
    559                     target_event += m_dimension; 
    560                 } 
    561             } 
    562             for(; j < read; ++j) { 
    563             // don't care for overflow 
    564                 float v = *buffer * multiplier;  // v: -231 .. 231 
    565                 unsigned int tmp = (int)v; 
    566                 *target_event = htonl((tmp >> 8) | 0x40000000); 
    567      
    568                 buffer++; 
    569                 target_event += m_dimension; 
    570             } 
    571  
    572             asm volatile("emms"); 
    573             break; 
    574         } 
    575         break; 
    576     } 
    577  
    578     return 0; 
    579 } 
    580  
    581 #else 
    582  
    583 int AmdtpTransmitStreamProcessor::encodePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    584         unsigned int offset, unsigned int nevents ) 
    585 { 
    586     unsigned int j=0; 
    587  
    588     quadlet_t *target_event; 
    589  
    590     target_event= ( quadlet_t * ) ( data + p->getPosition() ); 
    591  
    592     switch ( p->getDataType() ) 
    593     { 
    594         default: 
    595             debugError("bad type: %d\n", p->getDataType()); 
    596             return -1; 
    597         case Port::E_Int24: 
    598         { 
    599             quadlet_t *buffer= ( quadlet_t * ) ( p->getBufferAddress() ); 
    600522 
    601523            assert ( nevents + offset <= p->getBufferSize() ); 
     
    605527            for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    606528            { 
    607                 *target_event = htonl ( ( * ( buffer ) & 0x00FFFFFF ) | 0x40000000 ); 
    608                 buffer++; 
    609                 target_event += m_dimension; 
    610             } 
    611         } 
    612         break; 
    613         case Port::E_Float: 
    614         { 
    615             const float multiplier = ( float ) ( 0x7FFFFF00 ); 
    616             float *buffer= ( float * ) ( p->getBufferAddress() ); 
    617  
    618             assert ( nevents + offset <= p->getBufferSize() ); 
    619  
    620             buffer+=offset; 
    621  
    622             for ( j = 0; j < nevents; j += 1 )   // decode max nsamples 
    623             { 
    624529 
    625530                // don't care for overflow 
    626                 float v = *buffer * multiplier;  // v: -231 .. 231 
     531                float v = *buffer * AMDTP_FLOAT_MULTIPLIER;  // v: -231 .. 231 
    627532                unsigned int tmp = ( ( int ) v ); 
    628533                *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); 
     
    691596} 
    692597 
    693 #endif 
    694  
    695598int AmdtpTransmitStreamProcessor::encodeSilencePortToMBLAEvents ( AmdtpAudioPort *p, quadlet_t *data, 
    696599        unsigned int offset, unsigned int nevents ) 
     
    747650} 
    748651 
     652/** 
     653 * @brief encodes all audio ports in the cache to events 
     654 * @param data  
     655 * @param offset  
     656 * @param nevents  
     657 * @return  
     658 */ 
     659bool 
     660AmdtpTransmitStreamProcessor::encodeAudioPorts(quadlet_t *data, 
     661                                               unsigned int offset, 
     662                                               unsigned int nevents) 
     663{ 
     664    unsigned int j=0; 
     665 
     666    quadlet_t *target_event; 
     667    unsigned int i; 
     668    for (i = 0; i < m_nb_audio_ports; i++) { 
     669        struct _MBLA_port_cache p = m_audio_ports.at(i); 
     670        target_event = (quadlet_t *)(data + i); 
     671        assert(nevents + offset <= p.buffer_size ); 
     672 
     673        switch ( p.type ) 
     674        { 
     675            case Port::E_Float: 
     676            { 
     677                float *buffer = (float *)(p.buffer); 
     678                buffer += offset; 
     679 
     680                for (j = 0;j < nevents; j += 1)   // decode max nsamples 
     681                { 
     682                    // don't care for overflow 
     683                    float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER; 
     684                    unsigned int tmp = ((int) v); 
     685                    *target_event = htonl ( ( tmp >> 8 ) | 0x40000000 ); 
     686                    buffer++; 
     687                    target_event += m_dimension; 
     688                } 
     689            } 
     690            break; 
     691            case Port::E_Int24: 
     692            { 
     693                uint32_t *buffer = (uint32_t *)(p.buffer); 
     694                buffer += offset; 
     695 
     696                for (j = 0; j < nevents; j += 1)   // decode max nsamples 
     697                { 
     698                    *target_event = htonl(((*buffer) & 0x00FFFFFF) | 0x40000000); 
     699                    buffer++; 
     700                    target_event += m_dimension; 
     701                } 
     702            } 
     703            break; 
     704            default: 
     705                debugError("bad type: %d\n", m_audio_ports.at(i).type); 
     706                return false; 
     707        } 
     708    } 
     709    return true; 
     710} 
     711 
     712 
     713bool 
     714AmdtpTransmitStreamProcessor::initPortCache() { 
     715    // make use of the fact that audio ports are the first ports in 
     716    // the cluster as per AMDTP. so we can sort the ports by position 
     717    // and have very efficient lookups: 
     718    // m_float_ports.at(i).buffer -> audio stream i buffer 
     719    m_nb_audio_ports = 0; 
     720    m_audio_ports.clear(); 
     721     
     722    m_nb_midi_ports = 0; 
     723     
     724    for(PortVectorIterator it = m_Ports.begin(); 
     725        it != m_Ports.end(); 
     726        ++it ) 
     727    { 
     728        AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
     729        assert(pinfo); // this should not fail!! 
     730 
     731        switch( pinfo->getFormat() ) 
     732        { 
     733            case AmdtpPortInfo::E_MBLA: 
     734                m_nb_audio_ports++; 
     735                break; 
     736            case AmdtpPortInfo::E_SPDIF: // still unimplemented 
     737                break; 
     738            case AmdtpPortInfo::E_Midi: 
     739                m_nb_midi_ports++; 
     740                break; 
     741            default: // ignore 
     742                break; 
     743        } 
     744    } 
     745 
     746    unsigned int idx; 
     747    for (idx = 0; idx < m_nb_audio_ports; idx++) { 
     748        for(PortVectorIterator it = m_Ports.begin(); 
     749            it != m_Ports.end(); 
     750            ++it ) 
     751        { 
     752            AmdtpPortInfo *pinfo=dynamic_cast<AmdtpPortInfo *>(*it); 
     753            debugOutput(DEBUG_LEVEL_VERBOSE, "idx %u: looking at port %s at position %u\n", 
     754                                              idx, (*it)->getName().c_str(), pinfo->getPosition()); 
     755            if(pinfo->getPosition() == idx) { 
     756                struct _MBLA_port_cache p; 
     757                p.port = dynamic_cast<AmdtpAudioPort *>(*it); 
     758                if(p.port == NULL) { 
     759                    debugError("Port is not an AmdtpAudioPort!\n"); 
     760                    return false; 
     761                } 
     762//                p.position = pinfo->getPosition(); 
     763                p.buffer = NULL; // to be filled by updatePortCache 
     764                p.type = (*it)->getDataType(); 
     765#ifdef DEBUG 
     766                p.buffer_size = (*it)->getBufferSize(); 
     767#endif 
     768 
     769                m_audio_ports.push_back(p); 
     770                debugOutput(DEBUG_LEVEL_VERBOSE, "Cached port %s at position %u\n", 
     771                                                 p.port->getName().c_str(), idx); 
     772                goto next_index; 
     773            } 
     774        } 
     775        debugError("No MBLA port found for position %d\n", idx); 
     776        return false; 
     777next_index: 
     778        continue; 
     779    } 
     780 
     781    return true; 
     782} 
     783 
     784void 
     785AmdtpTransmitStreamProcessor::updatePortCache() { 
     786    unsigned int idx; 
     787    for (idx = 0; idx < m_nb_audio_ports; idx++) { 
     788        AmdtpAudioPort *port = m_audio_ports.at(idx).port; 
     789        m_audio_ports.at(idx).buffer = port->getBufferAddress(); 
     790    } 
     791} 
     792 
    749793} // end of namespace Streaming 
  • branches/api-cleanup/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h

    r809 r815  
    124124                                      unsigned int offset, unsigned int nevents); 
    125125 
     126    bool encodeAudioPorts(quadlet_t *data, unsigned int offset, unsigned int nevents); 
     127 
    126128    unsigned int getFDF(); 
    127129    unsigned int getSytInterval(); 
     
    132134    int m_fdf; 
    133135    unsigned int m_dbc; 
     136 
     137private: // local port caching for performance 
     138    struct _MBLA_port_cache { 
     139        AmdtpAudioPort*     port; 
     140        Port::E_DataType    type; 
     141        void*               buffer; 
     142#ifdef DEBUG 
     143        unsigned int        buffer_size; 
     144#endif 
     145    }; 
     146    std::vector<struct _MBLA_port_cache> m_audio_ports; 
     147    unsigned int m_nb_audio_ports; 
     148    unsigned int m_nb_midi_ports; 
     149 
     150    bool initPortCache(); 
     151    void updatePortCache(); 
     152 
    134153}; 
    135154 
  • branches/api-cleanup/src/libstreaming/generic/StreamProcessor.cpp

    r813 r815  
    474474                    // the process thread should have higher prio such that we are blocked until 
    475475                    // the samples are processed. 
     476                    return RAW1394_ISO_DEFER; 
    476477                } 
    477478            } 
     
    936937    } 
    937938    result = bufferfill > getNominalFramesPerPacket(); 
    938     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) for a bufferfill of %d, we return %d\n", 
    939                 this, ePTToString(getType()), bufferfill, result); 
     939    // debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) for a bufferfill of %d, we return %d\n", 
     940    //             this, ePTToString(getType()), bufferfill, result); 
    940941    return result; 
    941942} 
     
    10511052    if(m_scratch_buffer == NULL) { 
    10521053        debugFatal("Could not allocate scratch buffer\n"); 
     1054        return false; 
     1055    } 
     1056 
     1057    // set the parameters of ports we can: 
     1058    // we want the audio ports to be period buffered, 
     1059    // and the midi ports to be packet buffered 
     1060    for ( PortVectorIterator it = m_Ports.begin(); 
     1061        it != m_Ports.end(); 
     1062        ++it ) 
     1063    { 
     1064        debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
     1065        if(!(*it)->setBufferSize(m_StreamProcessorManager.getPeriodSize())) { 
     1066            debugFatal("Could not set buffer size to %d\n",m_StreamProcessorManager.getPeriodSize()); 
     1067            return false; 
     1068        } 
     1069    } 
     1070    // the API specific settings of the ports should already be set, 
     1071    // as this is called from the processorManager->prepare() 
     1072    // so we can init the ports 
     1073    if(!PortManager::initPorts()) { 
     1074        debugFatal("Could not initialize ports\n"); 
    10531075        return false; 
    10541076    } 
     
    12971319            result &= m_data_buffer->prepare(); // FIXME: the name 
    12981320 
    1299             // set the parameters of ports we can: 
    1300             // we want the audio ports to be period buffered, 
    1301             // and the midi ports to be packet buffered 
    1302             for ( PortVectorIterator it = m_Ports.begin(); 
    1303                 it != m_Ports.end(); 
    1304                 ++it ) 
    1305             { 
    1306                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str()); 
    1307                 if(!(*it)->setBufferSize(m_StreamProcessorManager.getPeriodSize())) { 
    1308                     debugFatal("Could not set buffer size to %d\n",m_StreamProcessorManager.getPeriodSize()); 
    1309                     return false; 
    1310                 } 
    1311             } 
    1312             // the API specific settings of the ports should already be set, 
    1313             // as this is called from the processorManager->prepare() 
    1314             // so we can init the ports 
    1315             result &= PortManager::initPorts(); 
    1316  
    13171321            break; 
    13181322        case ePS_DryRunning: 
  • branches/api-cleanup/tests/streaming/teststreaming3.cpp

    r812 r815  
    6767    long int sample_rate; 
    6868    long int rtprio; 
     69    long int audio_buffer_type; 
    6970    char* args[2]; 
    7071     
     
    8283    {"slave_mode",  's', "bool",  0,  "Run in slave mode" }, 
    8384    {"snoop_mode",  'S', "bool",  0,  "Run in snoop mode" }, 
     85    {"audio_buffer_type",  'b', "",  0,  "Datatype of audio buffers (0=float, 1=int24)" }, 
    8486    { 0 } 
    8587}; 
     
    156158            if ( errno ) { 
    157159                fprintf( stderr,  "Could not parse 'test-tone-freq' argument\n" ); 
     160                return ARGP_ERR_UNKNOWN; 
     161            } 
     162        } 
     163        break; 
     164    case 'b': 
     165        if (arg) { 
     166            arguments->audio_buffer_type = strtol( arg, &tail, 0 ); 
     167            if ( errno ) { 
     168                fprintf( stderr,  "Could not parse 'audio-buffer-type' argument\n" ); 
    158169                return ARGP_ERR_UNKNOWN; 
    159170            } 
     
    243254    arguments.sample_rate       = 44100; 
    244255    arguments.rtprio            = 0; 
     256    arguments.audio_buffer_type = 0; 
    245257     
    246258    // Parse our arguments; every option seen by `parse_opt' will 
     
    254266    setDebugLevel(arguments.verbose); 
    255267 
    256     int samplesread=0; 
    257 //     int sampleswritten=0; 
    258268    int nb_in_channels=0, nb_out_channels=0; 
    259269    int retval=0; 
     
    326336                /* assign the audiobuffer to the stream */ 
    327337                ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i])); 
    328                 ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_float); 
     338                if (arguments.audio_buffer_type == 0) { 
     339                    ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_float); 
     340                } else { 
     341                    ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_int24); 
     342                } 
    329343                ffado_streaming_capture_stream_onoff(dev, i, 1); 
    330344                break; 
     
    348362                /* assign the audiobuffer to the stream */ 
    349363                ffado_streaming_set_playback_stream_buffer(dev, i, (char *)(audiobuffers_out[i])); 
    350                 ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_float); 
     364                if (arguments.audio_buffer_type == 0) { 
     365                    ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_float); 
     366                } else { 
     367                    ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_int24); 
     368                } 
    351369                ffado_streaming_playback_stream_onoff(dev, i, 1); 
    352370                break; 
     
    414432            // generate the test tone 
    415433            for (i=0; i<arguments.period; i++) { 
    416                 nullbuffer[i] = amplitude * sin(sine_advance * (frame_counter + (float)i)); 
     434                float v = amplitude * sin(sine_advance * (frame_counter + (float)i)); 
     435                if (arguments.audio_buffer_type == 0) { 
     436                    nullbuffer[i] = v; 
     437                } else { 
     438                    v = (v * 2147483392.0); 
     439                    int32_t tmp = ((int) v); 
     440                    tmp = tmp >> 8; 
     441                    memcpy(&nullbuffer[i], &tmp, sizeof(float)); 
     442                } 
    417443            } 
    418444