Changeset 2444

Show
Ignore:
Timestamp:
01/22/12 02:03:21 (16 months ago)
Author:
wolke
Message:

bugfix against ticket 131 "the export song function don't support bpm changes in timeline"

tempo changing without use of rubberband batch processor is now possible.
the rubberband batch processor is not fast enough here. so i decide to disable them on audio export.

Location:
trunk/src
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/core/src/IO/DiskWriterDriver.h

    r2020 r2444  
    6161         
    6262                void write( float* buffer_L, float* buffer_R, unsigned int bufferSize ); 
    63          
     63 
     64                void audioEngine_process_checkBPMChanged(); 
     65 
    6466                unsigned getBufferSize() { 
    6567                        return m_nBufferSize; 
     
    8284        private: 
    8385 
     86 
    8487}; 
    8588 
  • trunk/src/core/src/IO/disk_writer_driver.cpp

    r2260 r2444  
    4040    Object* __object = ( Object* )param; 
    4141        DiskWriterDriver *pDriver = ( DiskWriterDriver* )param; 
     42        pDriver->setBpm( Hydrogen::get_instance()->getSong()->__bpm ); 
     43        pDriver->audioEngine_process_checkBPMChanged(); 
    4244        __INFOLOG( "DiskWriterDriver thread start" ); 
    4345 
     
    131133 
    132134 
    133         //calculate exact song length in frames (no loops). 
     135        Hydrogen* engine = Hydrogen::get_instance(); 
     136 
    134137        std::vector<PatternList*> *pPatternColumns = Hydrogen::get_instance()->getSong()->get_pattern_group_vector(); 
    135138        int nColumns = pPatternColumns->size(); 
    136139 
    137140        int nPatternSize; 
    138         int nSongSize = 0; 
    139         for ( int i = 0; i < nColumns; ++i ) { 
    140                 PatternList *pColumn = ( *pPatternColumns )[ i ]; 
     141        int validBpm = Hydrogen::get_instance()->getSong()->__bpm; 
     142        float ticksize = 0; 
     143        for ( int patternposition = 0; patternposition < nColumns; ++patternposition ) { 
     144                PatternList *pColumn = ( *pPatternColumns )[ patternposition ]; 
    141145                if ( pColumn->size() != 0 ) { 
    142146                        nPatternSize = pColumn->get( 0 )->get_length(); 
    143147                } else { 
    144148                        nPatternSize = MAX_NOTES; 
    145                 } 
    146                 nSongSize += nPatternSize; 
    147         } 
    148  
    149         float ticksize = pDriver->m_nSampleRate * 60.0 /  Hydrogen::get_instance()->getSong()->__bpm / 192 *4; 
    150          //here we have the song length in frames dependent from bpm and samplerate 
    151         unsigned songLengthInFrames = ticksize * nSongSize; 
    152  
    153         unsigned frameNumber = 0; 
    154         int lastRun = 0; 
    155         while ( frameNumber < songLengthInFrames ) { 
    156  
    157                 int usedBuffer = pDriver->m_nBufferSize; 
    158  
    159                 //this will calculate the the size from -last- (end of song) used frame buffer, 
    160                 //which is mostly smaller than pDriver->m_nBufferSize 
    161                 if( songLengthInFrames - frameNumber <  pDriver->m_nBufferSize ){ 
    162                         lastRun = songLengthInFrames - frameNumber; 
    163                         usedBuffer = lastRun; 
    164                 }; 
    165  
    166                 frameNumber += usedBuffer; 
    167                 int ret = pDriver->m_processCallback( usedBuffer, NULL ); 
    168  
    169                 for ( unsigned i = 0; i < usedBuffer; i++ ) { 
    170                         if(pData_L[i] > 1){ 
    171                                 pData[i * 2] = 1; 
    172                         } 
    173                         else if(pData_L[i] < -1){ 
    174                                 pData[i * 2] = -1; 
    175                         }else 
    176                         {  
    177                                 pData[i * 2] = pData_L[i]; 
    178                         } 
    179  
    180                         if(pData_R[i] > 1){ 
    181                                 pData[i * 2 + 1] = 1; 
    182                         } 
    183                         else if(pData_R[i] < -1){ 
    184                                 pData[i * 2 + 1] = -1; 
    185                         }else 
    186                         {  
    187                                 pData[i * 2 + 1] = pData_R[i]; 
    188                         } 
    189                 } 
    190                 int res = sf_writef_float( m_file, pData, usedBuffer ); 
    191                 if ( res != ( int )usedBuffer ) { 
    192                         __ERRORLOG( "Error during sf_write_float" ); 
    193                 } 
    194  
    195                 float fPercent = ( float ) frameNumber / ( float )songLengthInFrames * 100.0; 
    196                 EventQueue::get_instance()->push_event( EVENT_PROGRESS, ( int )fPercent ); 
    197 //              frameNuber += lastrun; 
    198         } 
     149                } 
     150 
     151                ticksize = pDriver->m_nSampleRate * 60.0 /  Hydrogen::get_instance()->getSong()->__bpm / Hydrogen::get_instance()->getSong()->__resolution; 
     152                // check pattern bpm if timeline bpm is in use 
     153                if(Preferences::get_instance()->__usetimeline){ 
     154                        if( engine->m_timelinevector.size() >= 1 ){ 
     155 
     156                                for ( int t = 0; t < engine->m_timelinevector.size(); t++){ 
     157                                        if(engine->m_timelinevector[t].m_htimelinebeat == patternposition && engine->m_timelinevector[t].m_htimelinebpm != validBpm){ 
     158                                                validBpm =  engine->m_timelinevector[t].m_htimelinebpm; 
     159                                        } 
     160 
     161                                } 
     162                        } 
     163                        pDriver->setBpm(validBpm); 
     164                        ticksize = pDriver->m_nSampleRate * 60.0 / validBpm / Hydrogen::get_instance()->getSong()->__resolution; 
     165                        pDriver->audioEngine_process_checkBPMChanged(); 
     166                        Hydrogen::get_instance()->setPatternPos(patternposition ); 
     167 
     168                } 
     169                else 
     170                { 
     171                        ticksize = pDriver->m_nSampleRate * 60.0 /  Hydrogen::get_instance()->getSong()->__bpm / Hydrogen::get_instance()->getSong()->__resolution; 
     172                        //pDriver->m_transport.m_nTickSize = ticksize; 
     173                } 
     174 
     175 
     176                 //here we have the song length in frames dependent from bpm and samplerate 
     177                unsigned patternLengthInFrames = ticksize * nPatternSize; 
     178         
     179                unsigned frameNumber = 0; 
     180                int lastRun = 0; 
     181                while ( frameNumber < patternLengthInFrames ) { 
     182         
     183                        int usedBuffer = pDriver->m_nBufferSize; 
     184         
     185                        //this will calculate the the size from -last- (end of song) used frame buffer, 
     186                        //which is mostly smaller than pDriver->m_nBufferSize 
     187                        if( patternLengthInFrames - frameNumber <  pDriver->m_nBufferSize ){ 
     188                                lastRun = patternLengthInFrames - frameNumber; 
     189                                usedBuffer = lastRun; 
     190                        }; 
     191         
     192                        frameNumber += usedBuffer; 
     193                        int ret = pDriver->m_processCallback( usedBuffer, NULL ); 
     194         
     195                        for ( unsigned i = 0; i < usedBuffer; i++ ) { 
     196                                if(pData_L[i] > 1){ 
     197                                        pData[i * 2] = 1; 
     198                                } 
     199                                else if(pData_L[i] < -1){ 
     200                                        pData[i * 2] = -1; 
     201                                }else 
     202                                { 
     203                                        pData[i * 2] = pData_L[i]; 
     204                                } 
     205         
     206                                if(pData_R[i] > 1){ 
     207                                        pData[i * 2 + 1] = 1; 
     208                                } 
     209                                else if(pData_R[i] < -1){ 
     210                                        pData[i * 2 + 1] = -1; 
     211                                }else 
     212                                { 
     213                                        pData[i * 2 + 1] = pData_R[i]; 
     214                                } 
     215                        } 
     216                        int res = sf_writef_float( m_file, pData, usedBuffer ); 
     217                        if ( res != ( int )usedBuffer ) { 
     218                                __ERRORLOG( "Error during sf_write_float" ); 
     219                        } 
     220                } 
     221 
     222                // this progress bar methode is not exact but ok enough to give users a usable visible progress feedback 
     223                float fPercent = ( float )(patternposition +1) / ( float )nColumns * 100.0; 
     224                EventQueue::get_instance()->push_event( EVENT_PROGRESS, ( int )fPercent ); 
     225        } 
    199226 
    200227        delete[] pData; 
     
    321348} 
    322349 
     350void DiskWriterDriver::audioEngine_process_checkBPMChanged() 
     351{ 
     352        float fNewTickSize = 
     353                        getSampleRate() * 60.0 
     354                        / Hydrogen::get_instance()->getSong()->__bpm 
     355                        / Hydrogen::get_instance()->getSong()->__resolution; 
     356 
     357        if ( fNewTickSize != m_transport.m_nTickSize ) { 
     358                // cerco di convertire ... 
     359                float fTickNumber = 
     360                                ( float )m_transport.m_nFrames 
     361                                / ( float )m_transport.m_nTickSize; 
     362 
     363                m_transport.m_nTickSize = fNewTickSize; 
     364 
     365                if ( m_transport.m_nTickSize == 0 ) { 
     366                        return; 
     367                } 
     368                long long nNewFrames = ( long long )( fTickNumber * fNewTickSize ); 
     369                // update frame position 
     370                m_transport.m_nFrames = nNewFrames; 
     371 
     372                // currently unuseble here 
     373                //EventQueue::get_instance()->push_event( EVENT_RECALCULATERUBBERBAND, -1); 
     374        } 
     375} 
    323376 
    324377}; 
  • trunk/src/core/src/hydrogen.cpp

    r2371 r2444  
    493493                        } 
    494494#endif 
    495                         EventQueue::get_instance()->push_event( EVENT_RECALCULATERUBBERBAND, -1); 
     495                        EventQueue::get_instance()->push_event( EVENT_RECALCULATERUBBERBAND, -1); 
    496496                } 
    497497        } 
     
    23852385        // reset 
    23862386        m_pAudioDriver->m_transport.m_nFrames = 0;      // reset total frames 
    2387         m_pAudioDriver->setBpm( m_pSong->__bpm ); 
     2387        //m_pAudioDriver->setBpm( m_pSong->__bpm ); 
    23882388        m_nSongPos = 0; 
    23892389        m_nPatternTickPosition = 0; 
  • trunk/src/gui/src/ExportSongDialog.cpp

    r2336 r2444  
    163163         
    164164        std::vector<Hydrogen::HTimelineVector> timelineVector = engine->m_timelinevector;  
    165         if( timelineVector.size() > 0 ){  
     165/*      if( timelineVector.size() > 0 ){ 
    166166                int res = QMessageBox::information( this, "Hydrogen", tr( "This version of hydrogen is not able to export songs with tempo changes. If you proceed, the song will be exported without tempo changes."), QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll);  
    167167                if (res == QMessageBox::No ) return;  
    168168                if (res == QMessageBox::YesToAll ) Preferences::get_instance()->setShowExportWarning(true); 
    169169        }  
    170  
     170*/ 
    171171        /* 0: Export to single track 
    172172        *  1: Export to multiple tracks