~raskolnikov/mixxx/round-bpm

« back to all changes in this revision

Viewing changes to mixxx/src/engine/enginebuffer.cpp

  • Committer: Juan Pedro Bolívar Puente
  • Date: 2012-01-07 15:14:58 UTC
  • mfrom: (2592.1.370 mixxx-trunk)
  • Revision ID: raskolnikov@gnu.org-20120107151458-mbgrbzlv7zmf75f2
Added missing files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
#include "engine/enginebuffer.h"
22
22
#include "cachingreader.h"
 
23
#include "sampleutil.h"
23
24
 
24
25
#include "controlpushbutton.h"
25
26
#include "controlobjectthreadmain.h"
79
80
    m_bScalerChanged(false),
80
81
    m_bLastBufferPaused(true),
81
82
    m_fRampValue(0.0),
82
 
    m_iRampState(ENGINE_RAMP_NONE)
83
 
{
 
83
    m_iRampState(ENGINE_RAMP_NONE),
 
84
    m_pDitherBuffer(new CSAMPLE[MAX_BUFFER_LEN]),
 
85
    m_iDitherBufferReadIndex(0) {
 
86
 
 
87
    // Generate dither values
 
88
    for (int i = 0; i < MAX_BUFFER_LEN; ++i) {
 
89
        m_pDitherBuffer[i] = static_cast<float>(rand() % 32768) / 32768.0 - 0.5;
 
90
    }
84
91
 
85
92
    m_fLastSampleValue[0] = 0;
86
93
    m_fLastSampleValue[1] = 0;
139
146
 
140
147
    // Actual rate (used in visuals, not for control)
141
148
    rateEngine = new ControlObject(ConfigKey(group, "rateEngine"));
142
 
    
 
149
 
143
150
    // BPM to display in the UI (updated more slowly than the actual bpm)
144
151
    visualBpm = new ControlObject(ConfigKey(group, "visual_bpm"));
145
152
 
259
266
    delete m_pKeylock;
260
267
    delete m_pEject;
261
268
 
 
269
    delete [] m_pDitherBuffer;
 
270
 
262
271
    while (m_engineControls.size() > 0) {
263
272
        EngineControl* pControl = m_engineControls.takeLast();
264
273
        delete pControl;
410
419
    if (!even((int)new_playpos))
411
420
        new_playpos--;
412
421
 
413
 
    // Give EngineControl's a chance to veto or correct the seek target.
414
 
 
415
 
    // Seek reader
416
 
    Hint seek_hint;
417
 
    seek_hint.sample = new_playpos;
418
 
    seek_hint.length = 0;
419
 
    seek_hint.priority = 1;
420
 
    QList<Hint> hint_list;
421
 
    hint_list.append(seek_hint);
422
 
    m_pReader->hintAndMaybeWake(hint_list);
423
422
    setNewPlaypos(new_playpos);
424
423
}
425
424
 
476
475
 
477
476
void EngineBuffer::process(const CSAMPLE *, const CSAMPLE * pOut, const int iBufferSize)
478
477
{
479
 
 
 
478
    Q_ASSERT(even(iBufferSize));
480
479
    m_pReader->process();
481
480
    // Steps:
482
481
    // - Lookup new reader information
489
488
    //   miscellaneous upkeep issues.
490
489
 
491
490
    CSAMPLE * pOutput = (CSAMPLE *)pOut;
492
 
 
493
491
    bool bCurBufferPaused = false;
494
492
    double rate = 0;
495
493
 
558
556
        if (!bCurBufferPaused) {
559
557
            CSAMPLE *output;
560
558
 
561
 
            Q_ASSERT(even(iBufferSize));
562
 
 
563
559
            // The fileposition should be: (why is this thing a double anyway!?
564
560
            // Integer valued.
565
 
            Q_ASSERT(round(filepos_play) == filepos_play);
 
561
            double filepos_play_rounded = round(filepos_play);
 
562
            if (filepos_play_rounded != filepos_play) {
 
563
                qWarning() << __FILE__ << __LINE__ << "ERROR: filepos_play is not round:" << filepos_play;
 
564
                filepos_play = filepos_play_rounded;
 
565
            }
 
566
 
566
567
            // Even.
567
 
            Q_ASSERT(even(filepos_play));
568
 
            
 
568
            if (!even(filepos_play)) {
 
569
                qWarning() << "ERROR: filepos_play is not even:" << filepos_play;
 
570
                filepos_play--;
 
571
            }
 
572
 
569
573
            // Perform scaling of Reader buffer into buffer.
570
574
            output = m_pScale->scale(0,
571
575
                                     iBufferSize,
605
609
                // stats-pipe once we have them.
606
610
 
607
611
                filepos_play = control_seek;
608
 
                Q_ASSERT(round(filepos_play) == filepos_play);
 
612
                double filepos_play_rounded = round(filepos_play);
 
613
                if (filepos_play_rounded != filepos_play) {
 
614
                    qWarning() << __FILE__ << __LINE__ << "ERROR: filepos_play is not round:" << filepos_play;
 
615
                    filepos_play = filepos_play_rounded;
 
616
                }
609
617
 
610
618
                // Fix filepos_play so that it is not out of bounds.
611
619
                if (file_length_old > 0) {
691
699
    //let's try holding the last sample value constant, and pull it
692
700
    //towards zero
693
701
    float ramp_inc = 0;
694
 
    if (m_iRampState == ENGINE_RAMP_UP || 
 
702
    if (m_iRampState == ENGINE_RAMP_UP ||
695
703
        m_iRampState == ENGINE_RAMP_DOWN) {
696
 
        ramp_inc = m_iRampState * 1000 / m_pSampleRate->get();
697
 
    }
698
 
 
699
 
    //float fakerate = rate * 30000 == 0 ? -5000 : rate*30000;
700
 
    for (int i=0; i<iBufferSize; i+=2) {
701
 
        if (bCurBufferPaused) {
702
 
            float dither = (float)(rand() % 32768) / 32768 - 0.5; // dither
703
 
            pOutput[i] = m_fLastSampleValue[0] * m_fRampValue + dither;
704
 
            pOutput[i+1] = m_fLastSampleValue[1] * m_fRampValue + dither;
705
 
        } else {
706
 
            pOutput[i] = pOutput[i] * m_fRampValue;
707
 
            pOutput[i+1] = pOutput[i+1] * m_fRampValue;
708
 
        }
709
 
 
710
 
        //writer << pOutput[i] <<  "\n";
711
 
        m_fRampValue += ramp_inc;
712
 
        if (m_fRampValue >= 1.0) {
713
 
            m_iRampState = ENGINE_RAMP_NONE;
714
 
            m_fRampValue = 1.0;
715
 
        }
716
 
        if (m_fRampValue <= 0.0) {
717
 
            m_iRampState = ENGINE_RAMP_NONE;
718
 
            m_fRampValue = 0.0;
719
 
        }
 
704
        ramp_inc = m_iRampState * 300 / m_pSampleRate->get();
 
705
 
 
706
        for (int i=0; i<iBufferSize; i+=2) {
 
707
            if (bCurBufferPaused) {
 
708
                float dither = m_pDitherBuffer[m_iDitherBufferReadIndex];
 
709
                m_iDitherBufferReadIndex = (m_iDitherBufferReadIndex + 1) % MAX_BUFFER_LEN;
 
710
                pOutput[i] = m_fLastSampleValue[0] * m_fRampValue + dither;
 
711
                pOutput[i+1] = m_fLastSampleValue[1] * m_fRampValue + dither;
 
712
            } else {
 
713
                pOutput[i] = pOutput[i] * m_fRampValue;
 
714
                pOutput[i+1] = pOutput[i+1] * m_fRampValue;
 
715
            }
 
716
 
 
717
            m_fRampValue += ramp_inc;
 
718
            if (m_fRampValue >= 1.0) {
 
719
                m_iRampState = ENGINE_RAMP_NONE;
 
720
                m_fRampValue = 1.0;
 
721
            }
 
722
            if (m_fRampValue <= 0.0) {
 
723
                m_iRampState = ENGINE_RAMP_NONE;
 
724
                m_fRampValue = 0.0;
 
725
            }
 
726
        }
 
727
    } else if (m_fRampValue == 0.0) {
 
728
        SampleUtil::applyGain(pOutput, 0.0, iBufferSize);
720
729
    }
721
730
 
722
731
    if ((!bCurBufferPaused && m_iRampState == ENGINE_RAMP_NONE) ||
725
734
        m_fLastSampleValue[1] = pOutput[iBufferSize-1];
726
735
    }
727
736
 
 
737
    /*for (int i=0; i<iBufferSize; i+=2) {
 
738
        writer << pOutput[i] <<  "\n";
 
739
    }*/
 
740
 
728
741
    m_bLastBufferPaused = bCurBufferPaused;
729
742
}
730
743
 
731
 
 
732
 
void EngineBuffer::rampOut(const CSAMPLE* pOut, int iBufferSize)
733
 
{
734
 
    CSAMPLE * pOutput = (CSAMPLE *)pOut;
735
 
 
736
 
    //qDebug() << "ramp out";
737
 
 
738
 
    // Ramp to zero
739
 
    int i=0;
740
 
    if (m_fLastSampleValue[0]!=0.) {
741
 
        // TODO(XXX) SSE
742
 
        if (pOutput[0] == 0) {
743
 
            while (i<iBufferSize) {
744
 
                float sigmoid = sigmoid_zero((float)(iBufferSize - i), (float)iBufferSize);
745
 
                float dither = (float)(rand() % 32768) / 32768 - 0.5; // dither
746
 
                pOutput[i] = (float)m_fLastSampleValue[0] * sigmoid + dither;
747
 
                pOutput[i+1] = (float)m_fLastSampleValue[1] * sigmoid + dither;
748
 
                i+=2;
749
 
            }
750
 
        } else {
751
 
            while (i<iBufferSize) {
752
 
                float sigmoid = sigmoid_zero((float)(iBufferSize - i), (float)iBufferSize);
753
 
                float dither = (float)(rand() % 32768) / 32768 - 0.5; // dither
754
 
                pOutput[i] = (float)pOutput[i] * sigmoid + dither;
755
 
                pOutput[i+1] = (float)pOutput[i+1] * sigmoid + dither;
756
 
                i+=2;
757
 
               }
758
 
        }
759
 
    }
760
 
 
761
 
    // TODO(XXX) memset
762
 
    // Reset rest of buffer
763
 
    while (i<iBufferSize)
764
 
    {
765
 
        pOutput[i]=0.;
766
 
        ++i;
767
 
    }
768
 
}
769
 
 
770
744
void EngineBuffer::updateIndicators(double rate, int iBufferSize) {
771
745
 
772
746
    // Increase samplesCalculated by the buffer size
788
762
 
789
763
        if(rate != rateEngine->get())
790
764
            rateEngine->set(rate);
791
 
            
 
765
 
792
766
        //Update the BPM even more slowly
793
767
        m_iUiSlowTick = (m_iUiSlowTick + 1) % kiBpmUpdateRate;
794
768
        if (m_iUiSlowTick == 0) {