root/trunk/libs/hydrogen/src/IO/disk_writer_driver.cpp @ 1468

Revision 1468, 8.1 KB (checked in by wolke, 4 years ago)

small codecleanup

Line 
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 *
21 */
22#include "DiskWriterDriver.h"
23
24#include <hydrogen/Preferences.h>
25#include <hydrogen/event_queue.h>
26#include <hydrogen/hydrogen.h>
27#include <hydrogen/Pattern.h>
28
29#include <pthread.h>
30#include <cassert>
31
32namespace H2Core
33{
34
35pthread_t diskWriterDriverThread;
36
37void* diskWriterDriver_thread( void* param )
38{
39        DiskWriterDriver *pDriver = ( DiskWriterDriver* )param;
40        _INFOLOG( "DiskWriterDriver thread start" );
41
42        // always rolling, no user interaction
43        pDriver->m_transport.m_status = TransportInfo::ROLLING;
44
45        SF_INFO soundInfo;
46        soundInfo.samplerate = pDriver->m_nSampleRate;
47//      soundInfo.frames = -1;//getNFrames();           ///\todo: da terminare
48        soundInfo.channels = 2;
49        //default format
50        int sfformat = 0x010000;
51        int bits = 0x0002;
52        //sf_format switch
53        if( pDriver->m_sFilename.endsWith(".aiff") || pDriver->m_sFilename.endsWith(".AIFF") )
54                sfformat =  0x020000;
55        if( pDriver->m_sFilename.endsWith(".flac") || pDriver->m_sFilename.endsWith(".FLAC") )
56                sfformat =  0x170000;
57
58        if( pDriver->m_nSampleDepth == 8 )
59                bits = 0x0001;
60        if( pDriver->m_nSampleDepth == 16 )
61                bits = 0x0002;
62        if( pDriver->m_nSampleDepth == 24 )
63                bits = 0x0003;
64        if( pDriver->m_nSampleDepth == 32 )
65                bits = 0x0004;
66
67        soundInfo.format =  sfformat|bits;
68
69        //ogg vorbis option
70        if( pDriver->m_sFilename.endsWith( ".ogg" ) | pDriver->m_sFilename.endsWith( ".OGG" ) )
71                soundInfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
72///format
73//          SF_FORMAT_WAV          = 0x010000,     /* Microsoft WAV format (little endian). */
74//          SF_FORMAT_AIFF         = 0x020000,     /* Apple/SGI AIFF format (big endian). */
75//          SF_FORMAT_AU           = 0x030000,     /* Sun/NeXT AU format (big endian). */
76//          SF_FORMAT_RAW          = 0x040000,     /* RAW PCM data. */
77//          SF_FORMAT_PAF          = 0x050000,     /* Ensoniq PARIS file format. */
78//          SF_FORMAT_SVX          = 0x060000,     /* Amiga IFF / SVX8 / SV16 format. */
79//          SF_FORMAT_NIST         = 0x070000,     /* Sphere NIST format. */
80//          SF_FORMAT_VOC          = 0x080000,     /* VOC files. */
81//          SF_FORMAT_IRCAM        = 0x0A0000,     /* Berkeley/IRCAM/CARL */
82//          SF_FORMAT_W64          = 0x0B0000,     /* Sonic Foundry's 64 bit RIFF/WAV */
83//          SF_FORMAT_MAT4         = 0x0C0000,     /* Matlab (tm) V4.2 / GNU Octave 2.0 */
84//          SF_FORMAT_MAT5         = 0x0D0000,     /* Matlab (tm) V5.0 / GNU Octave 2.1 */
85//          SF_FORMAT_PVF          = 0x0E0000,     /* Portable Voice Format */
86//          SF_FORMAT_XI           = 0x0F0000,     /* Fasttracker 2 Extended Instrument */
87//          SF_FORMAT_HTK          = 0x100000,     /* HMM Tool Kit format */
88//          SF_FORMAT_SDS          = 0x110000,     /* Midi Sample Dump Standard */
89//          SF_FORMAT_AVR          = 0x120000,     /* Audio Visual Research */
90//          SF_FORMAT_WAVEX        = 0x130000,     /* MS WAVE with WAVEFORMATEX */
91//          SF_FORMAT_SD2          = 0x160000,     /* Sound Designer 2 */
92//          SF_FORMAT_FLAC         = 0x170000,     /* FLAC lossless file format */
93//          SF_FORMAT_CAF          = 0x180000,     /* Core Audio File format */
94//          SF_FORMAT_OGG
95///bits
96//          SF_FORMAT_PCM_S8       = 0x0001,       /* Signed 8 bit data */
97//          SF_FORMAT_PCM_16       = 0x0002,       /* Signed 16 bit data */
98//          SF_FORMAT_PCM_24       = 0x0003,       /* Signed 24 bit data */
99//          SF_FORMAT_PCM_32       = 0x0004,       /* Signed 32 bit data */
100///used for ogg
101//          SF_FORMAT_VORBIS
102
103        if ( !sf_format_check( &soundInfo ) ) {
104                _ERRORLOG( "Error in soundInfo" );
105                return 0;
106        }
107
108
109        SNDFILE* m_file = sf_open( pDriver->m_sFilename.toLocal8Bit(), SFM_WRITE, &soundInfo );
110
111        float *pData = new float[ pDriver->m_nBufferSize * 2 ]; // always stereo
112
113        float *pData_L = pDriver->m_pOut_L;
114        float *pData_R = pDriver->m_pOut_R;
115
116
117        //calculate exaxt song frames.
118        std::vector<PatternList*> *pPatternColumns = Hydrogen::get_instance()->getSong()->get_pattern_group_vector();
119        int nColumns = pPatternColumns->size();
120
121        int nPatternSize;
122        int nSongSize = 0;
123        for ( int i = 0; i < nColumns; ++i ) {
124                PatternList *pColumn = ( *pPatternColumns )[ i ];
125                if ( pColumn->get_size() != 0 ) {
126                        nPatternSize = pColumn->get( 0 )->get_length();
127                } else {
128                        nPatternSize = MAX_NOTES;
129                }
130                nSongSize += nPatternSize;
131        }
132
133        float ticksize = pDriver->m_nSampleRate * 60.0 /  Hydrogen::get_instance()->getSong()->__bpm / 192 *4;
134        unsigned songLengthinFrames = ticksize * nSongSize;
135
136        unsigned frameNumber = 0;
137        int lastRun = 0;
138        while ( frameNumber < songLengthinFrames ) {
139
140                int usedBuffer = pDriver->m_nBufferSize;
141
142                if( songLengthinFrames - frameNumber <  pDriver->m_nBufferSize ){
143                        lastRun = songLengthinFrames - frameNumber;
144                        usedBuffer = lastRun;
145                };
146
147                frameNumber += usedBuffer;
148                int ret = pDriver->m_processCallback( usedBuffer, NULL );
149
150                for ( unsigned i = 0; i < usedBuffer; i++ ) {
151                        if(pData_L[i] > 1){
152                                pData[i * 2] = 1;
153                        }
154                        else if(pData_L[i] < -1){
155                                pData[i * 2] = -1;
156                        }else
157                        {
158                                pData[i * 2] = pData_L[i];
159                        }
160
161                        if(pData_R[i] > 1){
162                                pData[i * 2 + 1] = 1;
163                        }
164                        else if(pData_R[i] < -1){
165                                pData[i * 2 + 1] = -1;
166                        }else
167                        {
168                                pData[i * 2 + 1] = pData_R[i];
169                        }
170                }
171                int res = sf_writef_float( m_file, pData, usedBuffer );
172                if ( res != ( int )usedBuffer ) {
173                        _ERRORLOG( "Error during sf_write_float" );
174                }
175
176                float fPercent = ( float ) frameNumber / ( float )songLengthinFrames * 100.0;
177                EventQueue::get_instance()->push_event( EVENT_PROGRESS, ( int )fPercent );
178//              frameNuber += lastrun;
179        }
180
181        delete[] pData;
182        pData = NULL;
183
184        sf_close( m_file );
185
186        _INFOLOG( "DiskWriterDriver thread end" );
187
188        pthread_exit( NULL );
189
190        Hydrogen::get_instance()->stopExportSong();
191        return NULL;
192}
193
194
195
196
197DiskWriterDriver::DiskWriterDriver( audioProcessCallback processCallback, unsigned nSamplerate, const QString& sFilename, int nSampleDepth )
198                : AudioOutput( "DiskWriterDriver" )
199                , m_nSampleRate( nSamplerate )
200                , m_sFilename( sFilename )
201                , m_nSampleDepth ( nSampleDepth )
202                , m_processCallback( processCallback )
203{
204        INFOLOG( "INIT" );
205}
206
207
208
209DiskWriterDriver::~DiskWriterDriver()
210{
211        INFOLOG( "DESTROY" );
212}
213
214
215
216int DiskWriterDriver::init( unsigned nBufferSize )
217{
218        INFOLOG( QString( "Init, %1 samples" ).arg( nBufferSize ) );
219
220        m_nBufferSize = nBufferSize;
221        m_pOut_L = new float[nBufferSize];
222        m_pOut_R = new float[nBufferSize];
223
224        return 0;
225}
226
227
228
229///
230/// Connect
231/// return 0: Ok
232///
233int DiskWriterDriver::connect()
234{
235        INFOLOG( "[connect]" );
236
237        pthread_attr_t attr;
238        pthread_attr_init( &attr );
239
240        pthread_create( &diskWriterDriverThread, &attr, diskWriterDriver_thread, this );
241
242        return 0;
243}
244
245
246
247/// disconnect
248void DiskWriterDriver::disconnect()
249{
250        INFOLOG( "[disconnect]" );
251
252        delete[] m_pOut_L;
253        m_pOut_L = NULL;
254
255        delete[] m_pOut_R;
256        m_pOut_R = NULL;
257}
258
259
260
261unsigned DiskWriterDriver::getSampleRate()
262{
263        return m_nSampleRate;
264}
265
266
267
268void DiskWriterDriver::play()
269{
270        m_transport.m_status = TransportInfo::ROLLING;
271}
272
273
274
275void DiskWriterDriver::stop()
276{
277        m_transport.m_status = TransportInfo::STOPPED;
278}
279
280
281
282void DiskWriterDriver::locate( unsigned long nFrame )
283{
284        INFOLOG( QString( "Locate: %1" ).arg( nFrame ) );
285        m_transport.m_nFrames = nFrame;
286}
287
288
289
290void DiskWriterDriver::updateTransportInfo()
291{
292//      errorLog( "[updateTransportInfo] not implemented yet" );
293        // not used
294}
295
296
297
298void DiskWriterDriver::setBpm( float fBPM )
299{
300        INFOLOG( QString( "SetBpm: %1" ).arg( fBPM ) );
301        m_transport.m_nBPM = fBPM;
302}
303
304
305};
Note: See TracBrowser for help on using the browser.