~ubuntu-branches/ubuntu/hardy/lmms/hardy

« back to all changes in this revision

Viewing changes to src/lib/sample_buffer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Tobias Doerffel
  • Date: 2007-09-17 15:00:24 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070917150024-mo0zk4ks81jawqii
Tags: 0.3.0-1ubuntu1
* Resynchronized with Debian (LP: #139759, LP: #90806, LP: #102639,
  LP: #113447, LP: #121172, LP: #124890)
* reverted changes from 0.2.1-1.1ubuntu1 as upstream merged/included them

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
/*
4
4
 * sample_buffer.cpp - container-class sampleBuffer
5
5
 *
6
 
 * Copyright (c) 2005-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 
6
 * Copyright (c) 2005-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
7
7
 * 
8
8
 * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
9
9
 *
19
19
 *
20
20
 * You should have received a copy of the GNU General Public
21
21
 * License along with this program (see COPYING); if not, write to the
22
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23
 
 * Boston, MA 02111-1307, USA.
 
22
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
23
 * Boston, MA 02110-1301 USA.
24
24
 *
25
25
 */
26
26
 
36
36
#include <QtCore/QBuffer>
37
37
#include <QtCore/QFile>
38
38
#include <QtCore/QFileInfo>
39
 
#include <QtCore/QMutex>
40
39
#include <QtGui/QFileDialog>
41
40
#include <QtGui/QMessageBox>
42
41
#include <QtGui/QPainter>
44
43
#else
45
44
 
46
45
#include <qpainter.h>
47
 
#include <qmutex.h>
48
46
#include <qmessagebox.h>
49
47
#include <qfiledialog.h>
50
48
#include <qfileinfo.h>
83
81
 
84
82
#include "sample_buffer.h"
85
83
#include "interpolation.h"
86
 
#include "paths.h"
87
84
#include "templates.h"
88
85
#include "config_mgr.h"
89
86
#include "endian_handling.h"
 
87
#include "engine.h"
90
88
#include "base64.h"
91
89
#include "debug.h"
92
90
 
101
99
 
102
100
 
103
101
 
104
 
sampleBuffer::sampleBuffer( engine * _engine, const QString & _audio_file,
 
102
sampleBuffer::sampleBuffer( const QString & _audio_file,
105
103
                                                        bool _is_base64_data ) :
106
 
        QObject(),
107
 
        engineObject( _engine ),
108
104
        m_audioFile( ( _is_base64_data == TRUE ) ? "" : _audio_file ),
109
105
        m_origData( NULL ),
110
106
        m_origFrames( 0 ),
112
108
        m_frames( 0 ),
113
109
        m_startFrame( 0 ),
114
110
        m_endFrame( 0 ),
 
111
        m_loop_startFrame( 0 ),
 
112
        m_loop_endFrame( 0 ),
115
113
        m_amplification( 1.0f ),
116
114
        m_reversed( FALSE ),
117
 
        m_dataMutex()
 
115
        m_frequency( BASE_FREQ ),
 
116
        m_sample_rate( SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] ),
 
117
        m_sample_fragment( NULL )
118
118
{
119
119
#ifdef SDL_SDL_SOUND_H
120
120
        // init sound-file-system of SDL
121
121
        Sound_Init();
122
122
#endif
123
 
#ifdef HAVE_SAMPLERATE_H
124
123
        initResampling();
125
 
#endif
126
124
        if( _is_base64_data == TRUE )
127
125
        {
128
126
                loadFromBase64( _audio_file );
133
131
 
134
132
 
135
133
 
136
 
sampleBuffer::sampleBuffer( const sampleFrame * _data, const f_cnt_t _frames,
137
 
                                                        engine * _engine ) :
138
 
        QObject(),
139
 
        engineObject( _engine ),
 
134
sampleBuffer::sampleBuffer( const sampleFrame * _data, const f_cnt_t _frames ) :
140
135
        m_audioFile( "" ),
141
136
        m_origData( NULL ),
142
137
        m_origFrames( 0 ),
144
139
        m_frames( 0 ),
145
140
        m_startFrame( 0 ),
146
141
        m_endFrame( 0 ),
 
142
        m_loop_startFrame( 0 ),
 
143
        m_loop_endFrame( 0 ),
147
144
        m_amplification( 1.0f ),
148
145
        m_reversed( FALSE ),
149
 
        m_dataMutex()
 
146
        m_frequency( BASE_FREQ ),
 
147
        m_sample_rate( SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] ),
 
148
        m_sample_fragment( NULL )
150
149
{
151
150
        m_origData = new sampleFrame[_frames];
152
151
        memcpy( m_origData, _data, _frames * BYTES_PER_FRAME );
155
154
        // init sound-file-system of SDL
156
155
        Sound_Init();
157
156
#endif
158
 
#ifdef HAVE_SAMPLERATE_H
159
157
        initResampling();
160
 
#endif
161
158
        update();
162
159
}
163
160
 
164
161
 
165
162
 
166
163
 
167
 
sampleBuffer::sampleBuffer( const f_cnt_t _frames, engine * _engine ) :
168
 
        QObject(),
169
 
        engineObject( _engine ),
 
164
sampleBuffer::sampleBuffer( const f_cnt_t _frames ) :
170
165
        m_audioFile( "" ),
171
166
        m_origData( NULL ),
172
167
        m_origFrames( 0 ),
174
169
        m_frames( 0 ),
175
170
        m_startFrame( 0 ),
176
171
        m_endFrame( 0 ),
 
172
        m_loop_startFrame( 0 ),
 
173
        m_loop_endFrame( 0 ),
177
174
        m_amplification( 1.0f ),
178
175
        m_reversed( FALSE ),
179
 
        m_dataMutex()
 
176
        m_frequency( BASE_FREQ ),
 
177
        m_sample_rate( SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] ),
 
178
        m_sample_fragment( NULL )
180
179
{
181
180
        m_origData = new sampleFrame[_frames];
182
181
        memset( m_origData, 0, _frames * BYTES_PER_FRAME );
185
184
        // init sound-file-system of SDL
186
185
        Sound_Init();
187
186
#endif
188
 
#ifdef HAVE_SAMPLERATE_H
189
187
        initResampling();
190
 
#endif
191
188
        update();
192
189
}
193
190
 
196
193
 
197
194
sampleBuffer::~sampleBuffer()
198
195
{
199
 
        m_dataMutex.lock();
200
196
        delete[] m_origData;
201
 
        m_origData = NULL;
202
197
        delete[] m_data;
203
 
        m_data = NULL;
204
 
 
205
 
#ifdef HAVE_SAMPLERATE_H
206
 
        quitResampling();
207
 
#endif
208
 
 
209
 
        m_dataMutex.unlock();
 
198
        delete[] m_sample_fragment;
210
199
}
211
200
 
212
201
 
216
205
 
217
206
void sampleBuffer::update( bool _keep_settings )
218
207
{
219
 
        m_dataMutex.lock();
 
208
        engine::getMixer()->lock();
220
209
 
221
210
        delete[] m_data;
222
 
        m_data = NULL;
223
 
        m_frames = 0;
224
211
 
225
212
        if( m_audioFile == "" && m_origData != NULL && m_origFrames > 0 )
226
213
        {
231
218
                if( _keep_settings == FALSE )
232
219
                {
233
220
                        m_frames = m_origFrames;
234
 
                        m_startFrame = 0;
235
 
                        if( m_frames > 0 )
236
 
                        {
237
 
                                m_endFrame = m_frames - 1;
238
 
                        }
239
 
                        else
240
 
                        {
241
 
                                m_endFrame = 0;
242
 
                        }
 
221
                        m_loop_startFrame = m_startFrame = 0;
 
222
                        m_loop_endFrame = m_endFrame = m_frames;
243
223
                }
244
224
        }
245
225
        else if( m_audioFile != "" )
246
226
        {
247
 
                QString file = m_audioFile;
248
 
                // if there's not an absolute filename, we assume that we made
249
 
                // it relative before and so we have to add sample-dir to file-
250
 
                // name
251
 
                if( file[0] != '/' )
252
 
                {
253
 
                        file = configManager::inst()->userSamplesDir() + file;
254
 
                        if( QFileInfo( file ).exists() == FALSE )
255
 
                        {
256
 
                                file =
257
 
                configManager::inst()->factorySamplesDir() + m_audioFile;
258
 
                        }
259
 
                }
 
227
                QString file = tryToMakeAbsolute( m_audioFile );
260
228
                const char * f =
261
229
#ifdef QT4
262
230
                                file.toAscii().constData();
267
235
                ch_cnt_t channels = DEFAULT_CHANNELS;
268
236
                sample_rate_t samplerate = SAMPLE_RATES[DEFAULT_QUALITY_LEVEL];
269
237
 
 
238
                m_frames = 0;
 
239
 
270
240
#ifdef HAVE_SNDFILE_H
271
241
                if( m_frames == 0 )
272
242
                {
329
299
 
330
300
                        delete[] buf;
331
301
 
332
 
                        // do samplerate-conversion if sample-decoder didn't
333
 
                        // convert sample-rate to our default-samplerate
334
 
                        if( samplerate != SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] )
335
 
                        {
336
 
                                sampleBuffer * resampled = resample( this,
337
 
                                                                samplerate,
338
 
                                        SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] );
339
 
                                delete[] m_data;
340
 
                                m_frames = resampled->frames();
341
 
                                m_data = new sampleFrame[m_frames];
342
 
                                memcpy( m_data, resampled->data(), m_frames *
343
 
                                                        sizeof( sampleFrame ) );
344
 
                                delete resampled;
345
 
                        }
346
 
 
347
 
                        if( _keep_settings == FALSE )
348
 
                        {
349
 
                                // update frame-variables
350
 
                                m_startFrame = 0;
351
 
                                if( m_frames > 0 )
352
 
                                {
353
 
                                        m_endFrame = m_frames - 1;
354
 
                                }
355
 
                                else
356
 
                                {
357
 
                                        m_endFrame = 0;
358
 
                                }
359
 
                        }
 
302
                        normalize_sample_rate( samplerate, _keep_settings );
360
303
                }
361
304
                else
362
305
                {
365
308
                        m_data = new sampleFrame[1];
366
309
                        memset( m_data, 0, sizeof( *m_data ) );
367
310
                        m_frames = 1;
368
 
                        m_startFrame = 0;
369
 
                        m_endFrame = 1;
 
311
                        m_loop_startFrame = m_startFrame = 0;
 
312
                        m_loop_endFrame = m_endFrame = 1;
370
313
                }
371
314
        }
372
315
        else
374
317
                // neither an audio-file nor a buffer to copy from, so create
375
318
                // buffer containing one sample-frame
376
319
                m_data = new sampleFrame[1];
377
 
                memset( m_data, 0, sizeof( *m_data ) * 1 );
 
320
                memset( m_data, 0, sizeof( *m_data ) );
378
321
                m_frames = 1;
379
 
                m_startFrame = 0;
380
 
                m_endFrame = 1;
 
322
                m_loop_startFrame = m_startFrame = 0;
 
323
                m_loop_endFrame = m_endFrame = 1;
381
324
        }
382
325
 
383
 
        m_dataMutex.unlock();
 
326
        engine::getMixer()->unlock();
384
327
 
385
328
        emit sampleUpdated();
386
329
}
388
331
 
389
332
 
390
333
 
 
334
void sampleBuffer::normalize_sample_rate( const sample_rate_t _src_sr,
 
335
                                                        bool _keep_settings )
 
336
{
 
337
        // do samplerate-conversion to our default-samplerate
 
338
        if( _src_sr != SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] )
 
339
        {
 
340
                sampleBuffer * resampled = resample( this, _src_sr,
 
341
                                        SAMPLE_RATES[DEFAULT_QUALITY_LEVEL] );
 
342
                delete[] m_data;
 
343
                m_frames = resampled->frames();
 
344
                m_data = new sampleFrame[m_frames];
 
345
                memcpy( m_data, resampled->data(), m_frames *
 
346
                                                        sizeof( sampleFrame ) );
 
347
                delete resampled;
 
348
        }
 
349
 
 
350
        if( _keep_settings == FALSE )
 
351
        {
 
352
                // update frame-variables
 
353
                m_loop_startFrame = m_startFrame = 0;
 
354
                m_loop_endFrame = m_endFrame = m_frames;
 
355
        }
 
356
}
 
357
 
 
358
 
 
359
 
 
360
 
391
361
#ifdef SDL_SDL_SOUND_H
392
362
f_cnt_t sampleBuffer::decodeSampleSDL( const char * _f,
393
363
                                        int_sample_t * & _buf,
394
 
                                        ch_cnt_t & _channels,
395
 
                                        sample_rate_t & _samplerate )
 
364
                                        ch_cnt_t _channels,
 
365
                                        sample_rate_t _samplerate )
396
366
{
397
367
        Sound_AudioInfo STD_AUDIO_INFO =
398
368
        {
399
369
                AUDIO_S16SYS,
400
370
                _channels,
401
 
                _samplerate,
 
371
                _samplerate
402
372
        } ;
403
373
        f_cnt_t frames = 0;
404
374
 
409
379
        {
410
380
                // let SDL_sound decode our file to requested format
411
381
                ( void )Sound_DecodeAll( snd_sample );
412
 
                _channels = snd_sample->actual.channels;
413
 
                _samplerate = snd_sample->actual.rate;
414
382
                frames = snd_sample->buffer_size / ( BYTES_PER_INT_SAMPLE *
415
383
                                                                _channels );
416
384
                _buf = new int_sample_t[frames * _channels];
617
585
 
618
586
 
619
587
 
620
 
#ifdef HAVE_SAMPLERATE_H
621
588
void sampleBuffer::initResampling( void )
622
589
{
623
 
        m_srcState = createResamplingContext();
624
590
        m_srcData.end_of_input = 0;
625
591
}
626
592
 
627
593
 
628
594
 
629
595
 
630
 
void sampleBuffer::quitResampling( void )
631
 
{
632
 
        destroyResamplingContext( m_srcState );
633
 
}
634
 
 
635
 
 
636
 
 
637
 
 
638
 
SRC_STATE * sampleBuffer::createResamplingContext( void )
639
 
{
640
 
        int error;
641
 
        SRC_STATE * state;
642
 
        if( ( state = src_new(/*
643
 
                ( eng()->getMixer()->highQuality() == TRUE ) ?
644
 
                                        SRC_SINC_FASTEST :*/
645
 
                                        SRC_LINEAR,
646
 
                                        DEFAULT_CHANNELS, &error ) ) == NULL )
647
 
        {
648
 
                printf( "Error: src_new() failed in sample_buffer.cpp!\n" );
649
 
        }
650
 
        return( state );
651
 
}
652
 
 
653
 
 
654
 
 
655
 
 
656
 
void sampleBuffer::destroyResamplingContext( SRC_STATE * _context )
657
 
{
658
 
        src_delete( _context );
659
 
}
660
 
#endif
661
 
 
662
 
 
663
 
 
664
 
 
665
 
bool FASTCALL sampleBuffer::play( sampleFrame * _ab,
666
 
                                        const f_cnt_t _start_frame,
667
 
                                        const fpab_t _frames,
 
596
bool FASTCALL sampleBuffer::play( sampleFrame * _ab, handleState * _state,
 
597
                                        const fpp_t _frames,
668
598
                                        const float _freq,
669
 
                                        const bool _looped,
670
 
                                        void * * _resampling_data )
 
599
                                        const bool _looped )
671
600
{
672
 
        eng()->getMixer()->clearAudioBuffer( _ab, _frames );
 
601
        engine::getMixer()->clearAudioBuffer( _ab, _frames );
673
602
 
674
 
        if( m_data == NULL || m_frames == 0 || m_endFrame == 0 || _frames == 0 )
 
603
        if( m_endFrame == 0 || _frames == 0 )
675
604
        {
676
605
                return( FALSE );
677
606
        }
678
607
 
679
 
        const double freq_factor = (double) _freq / (double) BASE_FREQ;
680
 
        const Sint16 freq_diff = static_cast<Sint16>( BASE_FREQ - _freq );
681
 
 
682
 
        fpab_t frames_to_process = _frames;
 
608
        const double freq_factor = (double) _freq / (double) m_frequency
 
609
                        * m_sample_rate / engine::getMixer()->sampleRate();
683
610
 
684
611
        // calculate how many frames we have in requested pitch
685
612
        const f_cnt_t total_frames_for_current_pitch = static_cast<f_cnt_t>( (
690
617
                return( FALSE );
691
618
        }
692
619
 
693
 
        // do we have frames left?? this is only important when not in
694
 
        // looping-mode because in looping-mode we loop to start-frame...
695
 
        if( _start_frame >= total_frames_for_current_pitch && _looped == FALSE )
696
 
        {
697
 
                return( FALSE );
698
 
        }
699
 
 
700
620
        // this holds the number of the first frame to play
701
 
        const f_cnt_t play_frame = m_startFrame + ( _start_frame %
702
 
                                        total_frames_for_current_pitch );
 
621
        f_cnt_t play_frame = _state->m_frame_index;
 
622
        if( play_frame < m_startFrame )
 
623
        {
 
624
                play_frame = m_startFrame;
 
625
        }
703
626
 
704
627
        // this holds the number of remaining frames in current loop
705
 
        f_cnt_t frames_for_loop = total_frames_for_current_pitch -
706
 
                                                ( play_frame - m_startFrame );
707
 
 
708
 
        // make sure, data isn't accessed in any other way (e.g. deleting
709
 
        // of this buffer...)
710
 
        m_dataMutex.lock();
711
 
 
712
 
        if( _looped == FALSE && frames_for_loop < frames_to_process )
713
 
        {
714
 
                frames_to_process = frames_for_loop;
715
 
        }
716
 
        const f_cnt_t f1 = static_cast<f_cnt_t>( m_startFrame +
717
 
                                ( play_frame - m_startFrame ) * freq_factor );
718
 
/*      Uint32 f2 = 0;
719
 
        while( f2 < f1 )
720
 
        {
721
 
                f2 += frames_to_process * freq_factor;
722
 
        }
723
 
        if( f2 > f1 && f2 >= frames_to_process )
724
 
        {
725
 
                f2 -= frames_to_process * freq_factor;
726
 
        }*/
727
 
//      static int foo = 0;
728
 
        // calc pointer of first frame
729
 
        sampleFrame * start_frame = (sampleFrame *) m_data + f1;
730
 
        //printf("diff:%d %f  %d f2: %d  input: %d\n", f2 -foo, play_frame * freq_factor, static_cast<Uint32>( play_frame * freq_factor ), f2, (Uint32)( frames_for_loop * freq_factor ) );
731
 
//      foo = f2;
732
 
        sampleFrame * loop_start = (sampleFrame *) m_data + m_startFrame;
 
628
        f_cnt_t frames_for_loop;
 
629
        if( _looped )
 
630
        {
 
631
                play_frame = getLoopedIndex( play_frame );
 
632
                frames_for_loop = static_cast<f_cnt_t>(
 
633
                                        ( m_loop_endFrame - play_frame ) /
 
634
                                                                freq_factor );
 
635
        }
 
636
        else
 
637
        {
 
638
                if( play_frame >= m_endFrame )
 
639
                {
 
640
                        return( FALSE );
 
641
                }
 
642
                frames_for_loop = static_cast<f_cnt_t>(
 
643
                                        ( m_endFrame - play_frame ) /
 
644
                                                                freq_factor );
 
645
                if( frames_for_loop == 0 )
 
646
                {
 
647
                        return( FALSE );
 
648
                }
 
649
        }
733
650
 
734
651
        // check whether we have to change pitch...
735
 
        if( freq_diff != 0 )
 
652
        if( freq_factor != 1.0 || _state->m_varying_pitch )
736
653
        {
737
 
#ifdef HAVE_SAMPLERATE_H
738
 
                SRC_STATE * state = m_srcState;
739
 
                if( _resampling_data != NULL )
740
 
                {
741
 
                        if( _start_frame == 0 )
742
 
                        {
743
 
                                *_resampling_data = createResamplingContext();
744
 
                        }
745
 
                        state = static_cast<SRC_STATE *>( *_resampling_data );
746
 
                }
747
 
 
748
 
                // Check loop
749
 
                if( _looped && frames_for_loop < frames_to_process )
750
 
                {
751
 
                        f_cnt_t total_frames_copied = 0;
752
 
                        while( total_frames_copied < frames_to_process )
753
 
                        {
754
 
                                // Generate output
755
 
                                m_srcData.data_in = start_frame[0];
756
 
                                m_srcData.data_out = _ab[total_frames_copied];
757
 
                                m_srcData.input_frames = static_cast<f_cnt_t>(
758
 
                                                frames_for_loop * freq_factor );
759
 
                                m_srcData.output_frames = frames_for_loop;
760
 
                                m_srcData.src_ratio = 1.0 / freq_factor;
761
 
                                int error = src_process( state, &m_srcData );
762
 
                                if( error )
763
 
                                {
764
 
                                        printf( "sampleBuffer: error while "
765
 
                                                        "resampling: %s\n",
 
654
                // Generate output
 
655
                const f_cnt_t margin = 64;
 
656
                f_cnt_t fragment_size = (f_cnt_t)( _frames * freq_factor )
 
657
                                                                + margin;
 
658
                m_srcData.data_in = getSampleFragment( play_frame,
 
659
                                                fragment_size, _looped )[0];
 
660
                m_srcData.data_out = _ab[0];
 
661
                m_srcData.input_frames = fragment_size;
 
662
                m_srcData.output_frames = _frames;
 
663
                m_srcData.src_ratio = 1.0 / freq_factor;
 
664
                int error = src_process( _state->m_resampling_data,
 
665
                                                                &m_srcData );
 
666
                if( error )
 
667
                {
 
668
                        printf( "sampleBuffer: error while resampling: %s\n",
766
669
                                                        src_strerror( error ) );
767
 
                                }
768
 
                                // Advance
769
 
                                total_frames_copied += frames_for_loop;
770
 
 
771
 
                                // reset start_frame to start
772
 
                                start_frame = loop_start;
773
 
                                // and calculate frames for next loop
774
 
                                frames_for_loop = frames_to_process
775
 
                                                        - total_frames_copied;
776
 
                                if( frames_for_loop
777
 
                                        > total_frames_for_current_pitch )
778
 
                                {
779
 
                                        frames_for_loop =
780
 
                                                total_frames_for_current_pitch;
781
 
                                }
782
 
                        }
783
 
                }
784
 
                else
785
 
                {
786
 
                        // Generate output
787
 
                        m_srcData.data_in = start_frame[0];
788
 
                        m_srcData.data_out = _ab[0];
789
 
                        m_srcData.input_frames = static_cast<f_cnt_t>(
790
 
                                                frames_for_loop * freq_factor );
791
 
                        m_srcData.output_frames = frames_to_process;
792
 
                        m_srcData.src_ratio = 1.0 / freq_factor;
793
 
                        int error = src_process( state, &m_srcData );
794
 
                        if( error )
795
 
                        {
796
 
                                printf( "sampleBuffer: error while resampling: "
797
 
                                                "%s\n", src_strerror( error ) );
798
 
                        }
799
 
                }
800
 
#else
801
 
                f_cnt_t src_frame_base = 0;
802
 
                // check whether we're in high-quality-mode
803
 
                if( eng()->getMixer()->highQuality() == TRUE )
804
 
                {
805
 
                        // we are, so let's use cubic interpolation...
806
 
                        for( f_cnt_t frame = 0; frame < frames_to_process;
807
 
                                                                ++frame )
808
 
                        {
809
 
                                // current loop done?
810
 
                                if( _looped && ( frame-src_frame_base ) >
811
 
                                                        frames_for_loop )
812
 
                                {
813
 
                                        start_frame = loop_start;
814
 
                                        src_frame_base = frame;
815
 
                                        frames_for_loop = frames_to_process %
816
 
                                                total_frames_for_current_pitch;
817
 
                                }
818
 
 
819
 
                                const float src_frame_idx = frame * freq_factor;
820
 
                                f_cnt_t frame_num = static_cast<f_cnt_t>(
821
 
                                                src_frame_idx) - src_frame_base;
822
 
                                const float frac_pos = src_frame_idx -
823
 
                                        static_cast<f_cnt_t>( src_frame_idx );
824
 
 
825
 
                                // because of cubic interpolation we have to
826
 
                                // access start_frame[frame_num-1], so make
827
 
                                // sure we don't access data out of
828
 
                                // buffer-array-boundaries
829
 
                                if( frame_num == 0 && play_frame == 0 )
830
 
                                {
831
 
                                        frame_num = 1;
832
 
                                }
833
 
                                for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS;
834
 
                                                                        ++chnl )
835
 
                                {
836
 
                                        _ab[frame][chnl] = cubicInterpolate(
837
 
                                                start_frame[frame_num-1][chnl],
838
 
                                                start_frame[frame_num+0][chnl],
839
 
                                                start_frame[frame_num+1][chnl],
840
 
                                                start_frame[frame_num+2][chnl],
841
 
                                                                frac_pos );
842
 
                                }
843
 
                        }
844
 
                }
845
 
                else
846
 
                {
847
 
                        // just normal mode, so we can use linear
848
 
                        // interpolation...
849
 
                        for( f_cnt_t frame = 0; frame < frames_to_process;
850
 
                                                                ++frame )
851
 
                        {
852
 
                                if( _looped && ( frame - src_frame_base ) >
853
 
                                                        frames_for_loop )
854
 
                                {
855
 
                                        start_frame = loop_start;
856
 
                                        src_frame_base = frame;
857
 
                                        frames_for_loop = frames_to_process %
858
 
                                                total_frames_for_current_pitch;
859
 
                                }
860
 
                                const float src_frame_idx = frame * freq_factor;
861
 
                                const f_cnt_t frame_num =
862
 
                                        (f_cnt_t)src_frame_idx-src_frame_base;
863
 
                                const float frac_pos = src_frame_idx -
864
 
                                                        (f_cnt_t) src_frame_idx;
865
 
                                for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS;
866
 
                                                                        ++chnl )
867
 
                                {
868
 
                                        _ab[frame][chnl] = linearInterpolate(
869
 
                                                start_frame[frame_num][chnl],
870
 
                                                start_frame[frame_num+1][chnl],
871
 
                                                                frac_pos );
872
 
                                }
873
 
                        }
874
 
                }
875
 
#endif
 
670
                }
 
671
                if( m_srcData.output_frames_gen != _frames )
 
672
                {
 
673
                        printf( "sampleBuffer: not enough frames: %ld / %d\n",
 
674
                                        m_srcData.output_frames_gen, _frames );
 
675
                }
 
676
                // Advance
 
677
                play_frame += m_srcData.input_frames_used;
 
678
                if( _looped )
 
679
                {
 
680
                        play_frame = getLoopedIndex( play_frame );
 
681
                }
876
682
        }
877
683
        else
878
684
        {
879
685
                // we don't have to pitch, so we just copy the sample-data
880
686
                // as is into pitched-copy-buffer
881
687
 
882
 
                // Check loop
883
 
                if( _looped && frames_for_loop < frames_to_process )
884
 
                {
885
 
                        f_cnt_t total_frames_copied = 0;
886
 
                        while( total_frames_copied < frames_to_process )
887
 
                        {
888
 
                                // Generate output
889
 
                                memcpy( _ab[total_frames_copied], start_frame,
890
 
                                        frames_for_loop * BYTES_PER_FRAME );
891
 
                                // Advance
892
 
                                total_frames_copied += frames_for_loop;
893
 
 
894
 
                                // reset start_frame to start
895
 
                                start_frame = loop_start;
896
 
                                // and calculate frames for next loop
897
 
                                frames_for_loop = frames_to_process
898
 
                                                        - total_frames_copied;
899
 
                                if( frames_for_loop
900
 
                                        > total_frames_for_current_pitch )
901
 
                                {
902
 
                                        frames_for_loop =
903
 
                                                total_frames_for_current_pitch;
904
 
                                }
905
 
                        }
906
 
                }
907
 
                else
908
 
                {
909
 
                        // Generate output
910
 
                        memcpy( _ab, start_frame,
911
 
                                        frames_to_process * BYTES_PER_FRAME );
 
688
                // Generate output
 
689
                memcpy( _ab, getSampleFragment( play_frame, _frames, _looped ),
 
690
                                                _frames * BYTES_PER_FRAME );
 
691
                // Advance
 
692
                play_frame += _frames;
 
693
                if( _looped )
 
694
                {
 
695
                        play_frame = getLoopedIndex( play_frame );
912
696
                }
913
697
        }
914
698
 
915
 
        m_dataMutex.unlock();
 
699
        _state->m_frame_index = play_frame;
916
700
 
917
701
        return( TRUE );
918
702
 
921
705
 
922
706
 
923
707
 
 
708
sampleFrame * sampleBuffer::getSampleFragment( f_cnt_t _start,
 
709
                                                f_cnt_t _frames, bool _looped )
 
710
{
 
711
        if( _looped )
 
712
        {
 
713
                if( _start + _frames <= m_loop_endFrame )
 
714
                {
 
715
                        return( m_data + _start );
 
716
                }
 
717
        }
 
718
        else
 
719
        {
 
720
                if( _start + _frames <= m_endFrame )
 
721
                {
 
722
                        return( m_data + _start );
 
723
                }
 
724
        }
 
725
 
 
726
        delete[] m_sample_fragment;
 
727
        m_sample_fragment = new sampleFrame[_frames];
 
728
 
 
729
        if( _looped )
 
730
        {
 
731
                f_cnt_t copied = m_loop_endFrame - _start;
 
732
                memcpy( m_sample_fragment, m_data + _start, copied
 
733
                                                        * BYTES_PER_FRAME );
 
734
                f_cnt_t loop_frames = m_loop_endFrame - m_loop_startFrame;
 
735
                while( _frames - copied > 0 )
 
736
                {
 
737
                        f_cnt_t todo = tMin( _frames - copied, loop_frames );
 
738
                        memcpy( m_sample_fragment + copied,
 
739
                                                m_data + m_loop_startFrame,
 
740
                                                todo * BYTES_PER_FRAME );
 
741
                        copied += todo;
 
742
                }
 
743
        }
 
744
        else
 
745
        {
 
746
                f_cnt_t available = m_endFrame - _start;
 
747
                memcpy( m_sample_fragment, m_data + _start, available
 
748
                                                        * BYTES_PER_FRAME );
 
749
                memset( m_sample_fragment + available, 0, ( _frames -
 
750
                                                available ) * BYTES_PER_FRAME );
 
751
        }
 
752
 
 
753
        return( m_sample_fragment );
 
754
}
 
755
 
 
756
 
 
757
 
 
758
 
 
759
f_cnt_t sampleBuffer::getLoopedIndex( f_cnt_t _index )
 
760
{
 
761
        if( _index < m_loop_endFrame )
 
762
        {
 
763
                return( _index );
 
764
        }
 
765
        return( m_loop_startFrame + ( _index - m_loop_startFrame )
 
766
                                % ( m_loop_endFrame - m_loop_startFrame ) );
 
767
}
 
768
 
 
769
 
 
770
 
 
771
 
924
772
void sampleBuffer::visualize( QPainter & _p, const QRect & _dr,
925
773
                                        const QRect & _clip, drawMethods _dm )
926
774
{
939
787
 
940
788
        const QRect isect = _dr.intersect( _clip );
941
789
 
942
 
        if( m_data == NULL || m_frames == 0 )
943
 
        {
944
 
                _p.drawLine( isect.x(), y_base, isect.right(), y_base );
945
 
                return;
946
 
        }
947
 
        else if( _dm == LINE_CONNECT )
 
790
        if( _dm == LINE_CONNECT )
948
791
        {
949
792
#ifdef QT4
950
793
                float old_x = _dr.x();
1053
896
        // set filters
1054
897
#ifdef QT4
1055
898
        QStringList types;
1056
 
        types << tr( "All Audio-Files (*.wav *.ogg *.flac *.voc *.aif *.aiff "
1057
 
                                                                "*.au *.raw)" )
 
899
        types << tr( "All Audio-Files (*.wav *.ogg *.flac *.spx *.voc *.aif "
 
900
                                                        "*.aiff *.au *.raw)" )
1058
901
                << tr( "Wave-Files (*.wav)" )
1059
902
                << tr( "OGG-Files (*.ogg)" )
1060
903
                << tr( "FLAC-Files (*.flac)" )
 
904
                << tr( "SPEEX-Files (*.spx)" )
1061
905
                //<< tr( "MP3-Files (*.mp3)" )
1062
906
                //<< tr( "MIDI-Files (*.mid)" )
1063
907
                << tr( "VOC-Files (*.voc)" )
1068
912
                ;
1069
913
        ofd.setFilters( types );
1070
914
#else
1071
 
        ofd.addFilter( tr( "All Audio-Files (*.wav *.ogg *.flac *.voc *.aif "
1072
 
                                                "*.aiff *.au *.raw)" ) );
 
915
        ofd.addFilter( tr( "All Audio-Files (*.wav *.ogg *.flac *.spx *.voc "
 
916
                                                "*.aif *.aiff *.au *.raw)" ) );
1073
917
        ofd.addFilter( tr( "Wave-Files (*.wav)" ) );
1074
918
        ofd.addFilter( tr( "OGG-Files (*.ogg)" ) );
1075
919
        ofd.addFilter( tr( "FLAC-Files (*.flac)" ) );
 
920
        ofd.addFilter( tr( "SPEEX-Files (*.spx)" ) );
1076
921
        //ofd.addFilter (tr("MP3-Files (*.mp3)"));
1077
922
        //ofd.addFilter (tr("MIDI-Files (*.mid)"));^
1078
923
        ofd.addFilter( tr( "VOC-Files (*.voc)" ) );
1080
925
        ofd.addFilter( tr( "AU-Files (*.au)" ) );
1081
926
        ofd.addFilter( tr( "RAW-Files (*.raw)" ) );
1082
927
        //ofd.addFilter (tr("MOD-Files (*.mod)"));
1083
 
        ofd.setSelectedFilter( tr( "All Audio-Files (*.wav *.ogg *.flac *.voc "
1084
 
                                                "*.aif *.aiff *.au *.raw)" ) );
 
928
        ofd.setSelectedFilter( tr( "All Audio-Files (*.wav *.ogg *.flac *.spx "
 
929
                                        "*.voc *.aif *.aiff *.au *.raw)" ) );
1085
930
#endif
1086
931
        if( m_audioFile != "" )
1087
932
        {
1142
987
 
1143
988
QString & sampleBuffer::toBase64( QString & _dst ) const
1144
989
{
1145
 
        if( m_data == NULL || m_frames == 0 )
1146
 
        {
1147
 
                return( _dst = "" );
1148
 
        }
1149
 
 
1150
990
#ifdef HAVE_FLAC_STREAM_ENCODER_H
1151
991
        const f_cnt_t FRAMES_PER_BUF = 1152;
1152
992
 
1156
996
/*      FLAC__stream_encoder_set_do_exhaustive_model_search( flac_enc, TRUE );
1157
997
        FLAC__stream_encoder_set_do_mid_side_stereo( flac_enc, TRUE );*/
1158
998
        FLAC__stream_encoder_set_sample_rate( flac_enc,
1159
 
                                        eng()->getMixer()->sampleRate() );
 
999
                                        engine::getMixer()->sampleRate() );
1160
1000
        QBuffer ba_writer;
1161
1001
#ifdef QT4
1162
1002
        ba_writer.open( QBuffer::WriteOnly );
1217
1057
sampleBuffer * sampleBuffer::resample( sampleFrame * _data,
1218
1058
                                                const f_cnt_t _frames,
1219
1059
                                                const sample_rate_t _src_sr,
1220
 
                                                const sample_rate_t _dst_sr,
1221
 
                                                engine * _engine )
 
1060
                                                const sample_rate_t _dst_sr )
1222
1061
{
1223
1062
        const f_cnt_t dst_frames = static_cast<f_cnt_t>( _frames /
1224
1063
                                        (float) _src_sr * (float) _dst_sr );
1225
 
        sampleBuffer * dst_sb = new sampleBuffer( dst_frames, _engine );
 
1064
        sampleBuffer * dst_sb = new sampleBuffer( dst_frames );
1226
1065
        sampleFrame * dst_buf = dst_sb->m_origData;
1227
 
#ifdef HAVE_SAMPLERATE_H
 
1066
 
1228
1067
        // yeah, libsamplerate, let's rock with sinc-interpolation!
1229
1068
        int error;
1230
1069
        SRC_STATE * state;
1250
1089
        {
1251
1090
                printf( "Error: src_new() failed in sample_buffer.cpp!\n" );
1252
1091
        }
1253
 
#else
1254
 
        // no libsamplerate, so do simple cubic interpolation
1255
 
        for( f_cnt_t frame = 0; frame < dst_frames; ++frame )
1256
 
        {
1257
 
                const float src_frame_float = frame * (float) _src_sr / _dst_sr;
1258
 
                const float frac_pos = src_frame_float -
1259
 
                                        static_cast<f_cnt_t>( src_frame_float );
1260
 
                const f_cnt_t src_frame = tLimit<f_cnt_t>(
1261
 
                                        static_cast<f_cnt_t>( src_frame_float ),
1262
 
                                                        1, _frames - 3 );
1263
 
                for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch )
1264
 
                {
1265
 
                        dst_buf[frame][ch] = cubicInterpolate(
1266
 
                                                _data[src_frame - 1][ch],
1267
 
                                                _data[src_frame + 0][ch],
1268
 
                                                _data[src_frame + 1][ch],
1269
 
                                                _data[src_frame + 2][ch],
1270
 
                                                                frac_pos );
1271
 
                }
1272
 
        }
1273
 
#endif
1274
1092
        dst_sb->update();
1275
1093
        return( dst_sb );
1276
1094
}
1458
1276
 
1459
1277
void sampleBuffer::setStartFrame( const f_cnt_t _s )
1460
1278
{
1461
 
        // don't set this parameter while playing
1462
 
        m_dataMutex.lock();
1463
 
        m_startFrame = _s;
1464
 
        m_dataMutex.unlock();
 
1279
        m_loop_startFrame = m_startFrame = _s;
1465
1280
}
1466
1281
 
1467
1282
 
1469
1284
 
1470
1285
void sampleBuffer::setEndFrame( const f_cnt_t _e )
1471
1286
{
1472
 
        // don't set this parameter while playing
1473
 
        m_dataMutex.lock();
1474
 
        m_endFrame = _e;
1475
 
        m_dataMutex.unlock();
 
1287
        m_loop_endFrame = m_endFrame = _e;
1476
1288
}
1477
1289
 
1478
1290
 
1496
1308
 
1497
1309
 
1498
1310
 
1499
 
void sampleBuffer::deleteResamplingData( void * * _ptr )
1500
 
{
1501
 
#ifdef HAVE_SAMPLERATE_H
1502
 
#ifdef LMMS_DEBUG
1503
 
        assert( _ptr != NULL );
1504
 
        assert( *_ptr != NULL );
1505
 
#endif
1506
 
        destroyResamplingContext( static_cast<SRC_STATE *>( *_ptr ) );
1507
 
#endif
1508
 
        *_ptr = NULL;
1509
 
}
1510
 
 
1511
 
 
1512
 
 
1513
 
 
1514
1311
QString sampleBuffer::tryToMakeRelative( const QString & _file )
1515
1312
{
1516
1313
        if( QFileInfo( _file ).isRelative() == FALSE )
1517
1314
        {
1518
1315
                QString fsd = configManager::inst()->factorySamplesDir();
1519
1316
                QString usd = configManager::inst()->userSamplesDir();
1520
 
                if( _file.contains( fsd ) )
 
1317
                if( _file.startsWith( fsd ) )
1521
1318
                {
1522
 
                        return( QString( _file ).replace( fsd, "" ) );
 
1319
                        return( QString( _file ).mid( fsd.length() ) );
1523
1320
                }
1524
 
                else if( _file.contains( usd ) )
 
1321
                else if( _file.startsWith( usd ) )
1525
1322
                {
1526
 
                        return( QString( _file ).replace( usd, "" ) );
 
1323
                        return( QString( _file ).mid( usd.length() ) );
1527
1324
                }
1528
1325
        }
1529
1326
        return( _file );
1531
1328
 
1532
1329
 
1533
1330
 
 
1331
 
 
1332
QString sampleBuffer::tryToMakeAbsolute( const QString & _file )
 
1333
{
 
1334
        if( _file[0] == '/' )
 
1335
        {
 
1336
                return( _file );
 
1337
        }
 
1338
 
 
1339
        QString f = configManager::inst()->userSamplesDir() + _file;
 
1340
        if( QFileInfo( f ).exists() )
 
1341
        {
 
1342
                return( f );
 
1343
        }
 
1344
 
 
1345
        return( configManager::inst()->factorySamplesDir() + _file );
 
1346
}
 
1347
 
 
1348
 
 
1349
 
 
1350
 
 
1351
 
 
1352
 
 
1353
 
 
1354
 
 
1355
sampleBuffer::handleState::handleState( bool _varying_pitch ) :
 
1356
        m_frame_index( 0 ),
 
1357
        m_varying_pitch( _varying_pitch )
 
1358
{
 
1359
        int error;
 
1360
        if( ( m_resampling_data = src_new(/*
 
1361
                ( engine::getMixer()->highQuality() == TRUE ) ?
 
1362
                                        SRC_SINC_FASTEST :*/
 
1363
                                        SRC_LINEAR,
 
1364
                                        DEFAULT_CHANNELS, &error ) ) == NULL )
 
1365
        {
 
1366
                printf( "Error: src_new() failed in sample_buffer.cpp!\n" );
 
1367
        }
 
1368
}
 
1369
 
 
1370
 
 
1371
 
 
1372
 
 
1373
sampleBuffer::handleState::~handleState()
 
1374
{
 
1375
        src_delete( m_resampling_data );
 
1376
}
 
1377
 
 
1378
 
 
1379
 
 
1380
 
1534
1381
#undef write
1535
1382
#undef read
1536
1383
#undef pos