2012-05-26 14:49:10 +02:00
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: MP3Exporter.cpp 2992 2010-04-22 14:42:39Z lasconic $
//
// Copyright (C) 2011 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
# include "libmscore/score.h"
# include "fluid/fluid.h"
# include "libmscore/note.h"
# include "musescore.h"
# include "libmscore/part.h"
# include "preferences.h"
# include "seq.h"
# include "exportmp3.h"
//---------------------------------------------------------
// MP3Exporter
//---------------------------------------------------------
MP3Exporter : : MP3Exporter ( )
{
mLibraryLoaded = false ;
mEncoding = false ;
mGF = NULL ;
QSettings settings ;
mLibPath = settings . value ( " /Export/lameMP3LibPath " , " " ) . toString ( ) ;
mBitrate = 128 ;
mQuality = QUALITY_2 ;
mChannel = CHANNEL_STEREO ;
mMode = MODE_CBR ;
mRoutine = ROUTINE_FAST ;
}
MP3Exporter : : ~ MP3Exporter ( )
{
freeLibrary ( ) ;
}
//---------------------------------------------------------
// findLibrary
//---------------------------------------------------------
bool MP3Exporter : : findLibrary ( )
{
QString path ;
QString name ;
if ( ! mLibPath . isEmpty ( ) ) {
QFileInfo fi ( mLibPath ) ;
path = fi . absolutePath ( ) ;
name = fi . baseName ( ) ;
}
else {
path = getLibraryPath ( ) ;
name = getLibraryName ( ) ;
}
if ( noGui )
return false ;
QString libPath = QFileDialog : : getOpenFileName (
0 , mscore - > tr ( " Where is %1 ? " ) . arg ( getLibraryName ( ) ) ,
path ,
getLibraryTypeString ( ) ) ;
if ( libPath . isEmpty ( ) )
return false ;
QFileInfo fp ( libPath ) ;
if ( ! fp . exists ( ) )
return false ;
mLibPath = libPath ;
QSettings settings ;
settings . setValue ( " /Export/lameMP3LibPath " , mLibPath ) ;
return true ;
}
//---------------------------------------------------------
// loadLibrary
//---------------------------------------------------------
bool MP3Exporter : : loadLibrary ( AskUser askuser )
{
if ( validLibraryLoaded ( ) ) {
freeLibrary ( ) ;
mLibraryLoaded = false ;
}
// First try loading it from a previously located path
if ( ! mLibPath . isEmpty ( ) ) {
qDebug ( " Attempting to load LAME from previously defined path \n " ) ;
mLibraryLoaded = initLibrary ( mLibPath ) ;
}
// If not successful, try loading using system search paths
if ( ! validLibraryLoaded ( ) ) {
qDebug ( " Attempting to load LAME from system search paths \n " ) ;
mLibPath = getLibraryName ( ) ;
mLibraryLoaded = initLibrary ( mLibPath ) ;
}
// If not successful, try loading using compiled in path
if ( ! validLibraryLoaded ( ) ) {
qDebug ( " Attempting to load LAME from builtin path \n " ) ;
QFileInfo fn ( QDir ( getLibraryPath ( ) ) , getLibraryName ( ) ) ;
mLibPath = fn . absoluteFilePath ( ) ;
mLibraryLoaded = initLibrary ( mLibPath ) ;
}
// If not successful, must ask the user
if ( ! validLibraryLoaded ( ) ) {
qDebug ( " (Maybe) ask user for library \n " ) ;
int ret = QMessageBox : : question ( 0 , mscore - > tr ( " Save as MP3 " ) ,
mscore - > tr ( " MuseScore does not export MP3 files directly, but instead uses \n "
" the freely available LAME library. You must obtain %1 \n "
" separately, and then locate the file for MuseScore. \n "
" You only need to do this once. \n \n "
" Would you like to locate %2 now? " ) . arg ( getLibraryName ( ) ) . arg ( getLibraryName ( ) ) ,
QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : NoButton ) ;
if ( ret = = QMessageBox : : Yes & & askuser = = MP3Exporter : : Maybe & & findLibrary ( ) ) {
mLibraryLoaded = initLibrary ( mLibPath ) ;
}
}
// Oh well, just give up
if ( ! validLibraryLoaded ( ) ) {
qDebug ( " Failed to locate LAME library \n " ) ;
return false ;
}
qDebug ( " LAME library successfully loaded \n " ) ;
return true ;
}
bool MP3Exporter : : validLibraryLoaded ( )
{
return mLibraryLoaded ;
}
void MP3Exporter : : setMode ( int mode )
{
mMode = mode ;
}
void MP3Exporter : : setBitrate ( int rate )
{
mBitrate = rate ;
}
void MP3Exporter : : setQuality ( int q , int r )
{
mQuality = q ;
mRoutine = r ;
}
void MP3Exporter : : setChannel ( int mode )
{
mChannel = mode ;
}
//---------------------------------------------------------
// initLibrary
//---------------------------------------------------------
bool MP3Exporter : : initLibrary ( QString libpath )
{
qDebug ( " Loading LAME from %s \n " , qPrintable ( libpath ) ) ;
lame_lib = new QLibrary ( libpath , 0 ) ;
if ( ! lame_lib - > load ( ) ) {
2012-06-29 14:12:59 +02:00
qDebug ( " load failed <%s> \n " , qPrintable ( lame_lib - > errorString ( ) ) ) ;
2012-05-26 14:49:10 +02:00
return false ;
}
/*qDebug("Actual LAME path %s\n",
FileNames : : PathFromAddr ( lame_lib - > resolve ( " lame_init " ) ) ) ; */
lame_init = ( lame_init_t * )
lame_lib - > resolve ( " lame_init " ) ;
get_lame_version = ( get_lame_version_t * )
lame_lib - > resolve ( " get_lame_version " ) ;
lame_init_params = ( lame_init_params_t * )
lame_lib - > resolve ( " lame_init_params " ) ;
lame_encode_buffer_float = ( lame_encode_buffer_float_t * )
lame_lib - > resolve ( " lame_encode_buffer_float " ) ;
lame_encode_flush = ( lame_encode_flush_t * )
lame_lib - > resolve ( " lame_encode_flush " ) ;
lame_close = ( lame_close_t * )
lame_lib - > resolve ( " lame_close " ) ;
lame_set_in_samplerate = ( lame_set_in_samplerate_t * )
lame_lib - > resolve ( " lame_set_in_samplerate " ) ;
lame_set_out_samplerate = ( lame_set_out_samplerate_t * )
lame_lib - > resolve ( " lame_set_out_samplerate " ) ;
lame_set_num_channels = ( lame_set_num_channels_t * )
lame_lib - > resolve ( " lame_set_num_channels " ) ;
lame_set_quality = ( lame_set_quality_t * )
lame_lib - > resolve ( " lame_set_quality " ) ;
lame_set_brate = ( lame_set_brate_t * )
lame_lib - > resolve ( " lame_set_brate " ) ;
lame_set_VBR = ( lame_set_VBR_t * )
lame_lib - > resolve ( " lame_set_VBR " ) ;
lame_set_VBR_q = ( lame_set_VBR_q_t * )
lame_lib - > resolve ( " lame_set_VBR_q " ) ;
lame_set_VBR_min_bitrate_kbps = ( lame_set_VBR_min_bitrate_kbps_t * )
lame_lib - > resolve ( " lame_set_VBR_min_bitrate_kbps " ) ;
lame_set_mode = ( lame_set_mode_t * )
lame_lib - > resolve ( " lame_set_mode " ) ;
lame_set_preset = ( lame_set_preset_t * )
lame_lib - > resolve ( " lame_set_preset " ) ;
lame_set_error_protection = ( lame_set_error_protection_t * )
lame_lib - > resolve ( " lame_set_error_protection " ) ;
lame_set_disable_reservoir = ( lame_set_disable_reservoir_t * )
lame_lib - > resolve ( " lame_set_disable_reservoir " ) ;
lame_set_padding_type = ( lame_set_padding_type_t * )
lame_lib - > resolve ( " lame_set_padding_type " ) ;
lame_set_bWriteVbrTag = ( lame_set_bWriteVbrTag_t * )
lame_lib - > resolve ( " lame_set_bWriteVbrTag " ) ;
// These are optional
lame_get_lametag_frame = ( lame_get_lametag_frame_t * )
lame_lib - > resolve ( " lame_get_lametag_frame " ) ;
lame_mp3_tags_fid = ( lame_mp3_tags_fid_t * )
lame_lib - > resolve ( " lame_mp3_tags_fid " ) ;
# if defined(Q_WS_WIN)
beWriteInfoTag = ( beWriteInfoTag_t * )
lame_lib - > resolve ( " beWriteInfoTag " ) ;
beVersion = ( beVersion_t * )
lame_lib - > resolve ( " beVersion " ) ;
# endif
if ( ! lame_init | |
! get_lame_version | |
! lame_init_params | |
! lame_encode_buffer_float | |
! lame_encode_flush | |
! lame_close | |
! lame_set_in_samplerate | |
! lame_set_out_samplerate | |
! lame_set_num_channels | |
! lame_set_quality | |
! lame_set_brate | |
! lame_set_VBR | |
! lame_set_VBR_q | |
! lame_set_mode | |
! lame_set_preset | |
! lame_set_error_protection | |
! lame_set_disable_reservoir | |
! lame_set_padding_type | |
! lame_set_bWriteVbrTag ) {
qDebug ( " Failed to find a required symbol in the LAME library \n " ) ;
# if defined(Q_WS_WIN)
if ( beVersion ) {
be_version v ;
beVersion ( & v ) ;
mBladeVersion = QString ( " You are linking to lame_enc.dll v%d.%d. This version is not compatible with Audacity %d. \n Please download the latest version of the LAME MP3 library. " )
. arg ( v . byMajorVersion )
. arg ( v . byMinorVersion )
. arg ( 1 ) ; //TODO
}
# endif
lame_lib - > unload ( ) ;
delete lame_lib ;
return false ;
}
mGF = lame_init ( ) ;
if ( mGF = = NULL ) {
return false ;
}
return true ;
}
//---------------------------------------------------------
// freeLibrary
//---------------------------------------------------------
void MP3Exporter : : freeLibrary ( )
{
if ( mGF ) {
lame_close ( mGF ) ;
mGF = NULL ;
}
lame_lib - > unload ( ) ;
delete lame_lib ;
return ;
}
//---------------------------------------------------------
// getLibraryVersion
//---------------------------------------------------------
QString MP3Exporter : : getLibraryVersion ( )
{
if ( ! mLibraryLoaded )
return QString ( " " ) ;
return QString ( " LAME %s " ) . arg ( get_lame_version ( ) ) ;
}
//---------------------------------------------------------
// initializeStream
//---------------------------------------------------------
int MP3Exporter : : initializeStream ( int channels , int sampleRate )
{
if ( ! mLibraryLoaded )
return - 1 ;
if ( channels > 2 )
return - 1 ;
lame_set_error_protection ( mGF , false ) ;
lame_set_num_channels ( mGF , channels ) ;
lame_set_in_samplerate ( mGF , sampleRate ) ;
lame_set_out_samplerate ( mGF , sampleRate ) ;
lame_set_disable_reservoir ( mGF , true ) ;
lame_set_padding_type ( mGF , PAD_NO ) ;
// Add the VbrTag for all types. For ABR/VBR, a Xing tag will be created.
// For CBR, it will be a Lame Info tag.
lame_set_bWriteVbrTag ( mGF , true ) ;
// Set the VBR quality or ABR/CBR bitrate
switch ( mMode ) {
case MODE_SET :
{
int preset ;
if ( mQuality = = PRESET_INSANE )
preset = INSANE ;
else if ( mRoutine = = ROUTINE_FAST ) {
if ( mQuality = = PRESET_EXTREME )
preset = EXTREME_FAST ;
else if ( mQuality = = PRESET_STANDARD )
preset = STANDARD_FAST ;
else
preset = 1007 ; // Not defined until 3.96
}
else {
if ( mQuality = = PRESET_EXTREME )
preset = EXTREME ;
else if ( mQuality = = PRESET_STANDARD )
preset = STANDARD ;
else
preset = 1006 ; // Not defined until 3.96
}
lame_set_preset ( mGF , preset ) ;
}
break ;
case MODE_VBR :
lame_set_VBR ( mGF , ( mRoutine = = ROUTINE_STANDARD ? vbr_rh : vbr_mtrh ) ) ;
lame_set_VBR_q ( mGF , mQuality ) ;
break ;
case MODE_ABR :
lame_set_preset ( mGF , mBitrate ) ;
break ;
default :
lame_set_VBR ( mGF , vbr_off ) ;
lame_set_brate ( mGF , mBitrate ) ;
break ;
}
// Set the channel mode
MPEG_mode mode ;
if ( channels = = 1 )
mode = MONO ;
else if ( mChannel = = CHANNEL_JOINT )
mode = JOINT_STEREO ;
else
mode = STEREO ;
lame_set_mode ( mGF , mode ) ;
int rc = lame_init_params ( mGF ) ;
if ( rc < 0 )
return rc ;
#if 0
dump_config ( mGF ) ;
# endif
mInfoTagLen = 0 ;
mEncoding = true ;
return mSamplesPerChunk ;
}
//---------------------------------------------------------
// getOutBufferSize
//---------------------------------------------------------
int MP3Exporter : : getOutBufferSize ( )
{
if ( ! mEncoding )
return - 1 ;
return mOutBufferSize ;
}
//---------------------------------------------------------
// bufferPreamp
//---------------------------------------------------------
void MP3Exporter : : bufferPreamp ( float buffer [ ] , int nSamples )
{
for ( int i = 0 ; i < nSamples ; i + + )
buffer [ i ] = buffer [ i ] * 32768 ;
}
//---------------------------------------------------------
// encodeBuffer
//---------------------------------------------------------
int MP3Exporter : : encodeBuffer ( float inbufferL [ ] , float inbufferR [ ] , unsigned char outbuffer [ ] )
{
if ( ! mEncoding )
return - 1 ;
bufferPreamp ( inbufferL , mSamplesPerChunk ) ;
bufferPreamp ( inbufferR , mSamplesPerChunk ) ;
return lame_encode_buffer_float ( mGF , inbufferL , inbufferR , mSamplesPerChunk ,
outbuffer , mOutBufferSize ) ;
}
//---------------------------------------------------------
// encodeRemainder
//---------------------------------------------------------
int MP3Exporter : : encodeRemainder ( float inbufferL [ ] , float inbufferR [ ] , int nSamples ,
unsigned char outbuffer [ ] )
{
if ( ! mEncoding )
return - 1 ;
bufferPreamp ( inbufferL , nSamples ) ;
bufferPreamp ( inbufferR , nSamples ) ;
return lame_encode_buffer_float ( mGF , inbufferL , inbufferR , nSamples , outbuffer ,
mOutBufferSize ) ;
}
//---------------------------------------------------------
// encodeBufferMono
//---------------------------------------------------------
int MP3Exporter : : encodeBufferMono ( float inbuffer [ ] , unsigned char outbuffer [ ] )
{
if ( ! mEncoding )
return - 1 ;
bufferPreamp ( inbuffer , mSamplesPerChunk ) ;
return lame_encode_buffer_float ( mGF , inbuffer , inbuffer , mSamplesPerChunk ,
outbuffer , mOutBufferSize ) ;
}
//---------------------------------------------------------
// encodeRemainderMono
//---------------------------------------------------------
int MP3Exporter : : encodeRemainderMono ( float inbuffer [ ] , int nSamples ,
unsigned char outbuffer [ ] )
{
if ( ! mEncoding )
return - 1 ;
bufferPreamp ( inbuffer , nSamples ) ;
return lame_encode_buffer_float ( mGF , inbuffer , inbuffer , nSamples , outbuffer ,
mOutBufferSize ) ;
}
//---------------------------------------------------------
// finishStream
//---------------------------------------------------------
int MP3Exporter : : finishStream ( unsigned char outbuffer [ ] )
{
if ( ! mEncoding )
return - 1 ;
mEncoding = false ;
int result = lame_encode_flush ( mGF , outbuffer , mOutBufferSize ) ;
if ( lame_get_lametag_frame )
mInfoTagLen = lame_get_lametag_frame ( mGF , mInfoTagBuf , sizeof ( mInfoTagBuf ) ) ;
return result ;
}
//---------------------------------------------------------
// cancelEncoding
//---------------------------------------------------------
void MP3Exporter : : cancelEncoding ( )
{
mEncoding = false ;
}
/*void MP3Exporter::PutInfoTag(QFile f, qint64 off)
{
QDataStream out ( & f ) ;
if ( mGF ) {
if ( mInfoTagLen > 0 ) {
out . skipRawData ( off ) ;
out . writeRawData ( mInfoTagBuf , mInfoTagLen ) ;
}
# if defined(Q_WS_WIN)
else if ( beWriteInfoTag ) {
f . flush ( ) ;
QFileInfo fi ( f ) ;
beWriteInfoTag ( mGF , qPrintable ( fi . baseName ( ) ) ) ;
mGF = NULL ;
}
# endif
else if ( lame_mp3_tags_fid ) {
std : : FILE * fp ;
if ( ( fp = std : : fdopen ( file . handle ( ) , " w+ " ) ) ! = NULL )
lame_mp3_tags_fid ( mGF , fp ) ;
}
}
f . seek ( f . size ( ) ) ;
} */
# if defined(Q_WS_WIN)
/* values for Windows */
QString MP3Exporter : : getLibraryPath ( )
{
QSettings settings ( " HKEY_LOCAL_MACHINE \\ Software \\ Lame for Audacity " , QSettings : : NativeFormat ) ;
QString sReturnedValue = settings . value ( " InstallPath " , " " ) . toString ( ) ;
if ( ! sReturnedValue . isEmpty ( ) ) {
return sReturnedValue ;
}
return QDir : : rootPath ( ) ;
}
QString MP3Exporter : : getLibraryName ( )
{
return QString ( " lame_enc.dll " ) ;
}
QString MP3Exporter : : getLibraryTypeString ( )
{
return QString ( " Only lame_enc.dll (lame_enc.dll) ; ; Dynamically Linked Libraries ( * . dll ) ; ; All Files ( * . * ) " ) ;
}
# elif defined(Q_WS_MAC)
/* values for Mac OS X */
QString MP3Exporter : : getLibraryPath ( )
{
return QString ( " /usr/local/lib/audacity " ) ;
}
QString MP3Exporter : : getLibraryName ( )
{
return QString ( " libmp3lame.dylib " ) ;
}
QString MP3Exporter : : getLibraryTypeString ( )
{
return QString ( " Only libmp3lame.dylib (libmp3lame.dylib) ; ; Dynamic Libraries ( * . dylib ) ; ; All Files ( * ) " ) ;
}
# else //!Q_WS_MAC
/* Values for Linux / Unix systems */
QString MP3Exporter : : getLibraryPath ( )
{
return QString ( " /usr/lib " ) ;
}
QString MP3Exporter : : getLibraryName ( )
{
return QString ( " libmp3lame.so.0 " ) ;
}
QString MP3Exporter : : getLibraryTypeString ( )
{
return QString ( " Only libmp3lame.so.0 (libmp3lame.so.0) ; ; Primary Shared Object files ( * . so ) ; ; Extended Libraries ( * . so * ) ; ; All Files ( * ) " ) ;
}
# endif //mac
//---------------------------------------------------------
// saveMp3
//---------------------------------------------------------
bool MuseScore : : saveMp3 ( Score * score , const QString & name )
{
MP3Exporter exporter ;
if ( ! exporter . loadLibrary ( MP3Exporter : : Maybe ) ) {
QSettings settings ;
settings . setValue ( " /Export/lameMP3LibPath " , " " ) ;
if ( ! noGui )
QMessageBox : : warning ( 0 ,
tr ( " Error opening lame library " ) ,
tr ( " Could not open MP3 encoding library! " ) ,
QString : : null , QString : : null ) ;
qDebug ( " Could not open MP3 encoding library! \n " ) ;
return false ;
}
if ( ! exporter . validLibraryLoaded ( ) ) {
QSettings settings ;
settings . setValue ( " /Export/lameMP3LibPath " , " " ) ;
if ( ! noGui )
QMessageBox : : warning ( 0 ,
tr ( " Error opening lame library " ) ,
tr ( " Not a valid or supported MP3 encoding library! " ) ,
QString : : null , QString : : null ) ;
qDebug ( " Not a valid or supported MP3 encoding library! \n " ) ;
return false ;
}
// Retrieve preferences
// int highrate = 48000;
// int lowrate = 8000;
int bitrate = 0 ;
// int brate = 128;
// int rmode = MODE_CBR;
// int vmode = ROUTINE_FAST;
// int cmode = CHANNEL_STEREO;
int channels = 2 ;
2012-06-21 13:38:13 +02:00
int oldSampleRate = MScore : : sampleRate ;
int sampleRate = preferences . exportAudioSampleRate ;
2012-05-26 14:49:10 +02:00
exporter . setMode ( MODE_CBR ) ;
exporter . setBitrate ( bitrate ) ;
exporter . setChannel ( CHANNEL_STEREO ) ;
int inSamples = exporter . initializeStream ( channels , sampleRate ) ;
if ( inSamples < 0 ) {
2012-06-21 13:38:13 +02:00
if ( ! noGui ) {
QMessageBox : : warning ( 0 , tr ( " Encoding error " ) ,
tr ( " Unable to initialize MP3 stream " ) ,
QString : : null , QString : : null ) ;
}
2012-05-26 14:49:10 +02:00
qDebug ( " Unable to initialize MP3 stream \n " ) ;
2012-06-21 13:38:13 +02:00
MScore : : sampleRate = oldSampleRate ;
2012-05-26 14:49:10 +02:00
return false ;
}
QFile file ( name ) ;
2012-06-21 13:38:13 +02:00
if ( ! file . open ( QIODevice : : WriteOnly ) ) {
if ( ! noGui ) {
2012-05-26 14:49:10 +02:00
QMessageBox : : warning ( 0 ,
2012-06-21 13:38:13 +02:00
tr ( " Encoding error " ) ,
tr ( " Unable to open target file for writing " ) ,
QString : : null , QString : : null ) ;
}
MScore : : sampleRate = oldSampleRate ;
2012-05-26 14:49:10 +02:00
return false ;
}
2012-06-21 13:38:13 +02:00
int bufferSize = exporter . getOutBufferSize ( ) ;
uchar * bufferOut = new uchar [ bufferSize ] ;
2012-05-26 14:49:10 +02:00
MasterSynth * synti = new MasterSynth ( ) ;
synti - > init ( sampleRate ) ;
synti - > setState ( score - > syntiState ( ) ) ;
EventMap events ;
score - > toEList ( & events ) ;
QProgressBar * pBar = showProgressBar ( ) ;
pBar - > reset ( ) ;
2012-06-21 13:38:13 +02:00
static const int FRAMES = 512 ;
float bufferL [ FRAMES ] ;
float bufferR [ FRAMES ] ;
float peak = 0.0 ;
2012-05-26 14:49:10 +02:00
double gain = 1.0 ;
for ( int pass = 0 ; pass < 2 ; + + pass ) {
EventMap : : const_iterator playPos ;
playPos = events . constBegin ( ) ;
EventMap : : const_iterator endPos = events . constEnd ( ) ;
- - endPos ;
double et = score - > utick2utime ( endPos . key ( ) ) ;
et + = 1.0 ; // add trailer (sec)
pBar - > setRange ( 0 , int ( et ) ) ;
//
// init instruments
//
foreach ( const Part * part , score - > parts ( ) ) {
foreach ( const Channel & a , part - > instr ( ) - > channel ( ) ) {
a . updateInitList ( ) ;
foreach ( Event e , a . init ) {
if ( e . type ( ) = = ME_INVALID )
continue ;
e . setChannel ( a . channel ) ;
int syntiIdx = score - > midiMapping ( a . channel ) - > articulation - > synti ;
synti - > play ( e , syntiIdx ) ;
}
}
}
double playTime = 0.0 ;
synti - > setGain ( gain ) ;
for ( ; ; ) {
unsigned frames = FRAMES ;
//
// collect events for one segment
//
memset ( bufferL , 0 , sizeof ( float ) * FRAMES ) ;
memset ( bufferR , 0 , sizeof ( float ) * FRAMES ) ;
double endTime = playTime + double ( frames ) / double ( sampleRate ) ;
2012-06-21 13:38:13 +02:00
2012-05-26 14:49:10 +02:00
float * l = bufferL ;
float * r = bufferR ;
2012-06-21 13:38:13 +02:00
2012-05-26 14:49:10 +02:00
for ( ; playPos ! = events . constEnd ( ) ; + + playPos ) {
double f = score - > utick2utime ( playPos . key ( ) ) ;
if ( f > = endTime )
break ;
int n = lrint ( ( f - playTime ) * sampleRate ) ;
2012-06-21 13:38:13 +02:00
if ( n ) {
float bu [ n * 2 ] ;
memset ( bu , 0 , sizeof ( float ) * 2 * n ) ;
synti - > process ( n , bu ) ;
float * sp = bu ;
for ( int i = 0 ; i < n ; + + i ) {
* l + + = * sp + + ;
* r + + = * sp + + ;
}
playTime + = double ( n ) / double ( sampleRate ) ;
frames - = n ;
2012-05-26 14:49:10 +02:00
}
const Event & e = playPos . value ( ) ;
if ( e . isChannelEvent ( ) ) {
int channelIdx = e . channel ( ) ;
Channel * c = score - > midiMapping ( channelIdx ) - > articulation ;
if ( ! c - > mute ) {
synti - > play ( e , c - > synti ) ;
}
}
}
if ( frames ) {
float bu [ frames * 2 ] ;
2012-06-21 13:38:13 +02:00
memset ( bu , 0 , sizeof ( float ) * 2 * frames ) ;
2012-05-26 14:49:10 +02:00
synti - > process ( frames , bu ) ;
float * sp = bu ;
for ( unsigned i = 0 ; i < frames ; + + i ) {
* l + + = * sp + + ;
* r + + = * sp + + ;
}
playTime + = double ( frames ) / double ( sampleRate ) ;
}
if ( pass = = 1 ) {
2012-06-21 13:38:13 +02:00
long bytes ;
if ( FRAMES < inSamples )
bytes = exporter . encodeRemainder ( bufferL , bufferR , FRAMES , bufferOut ) ;
else
bytes = exporter . encodeBuffer ( bufferL , bufferR , bufferOut ) ;
if ( bytes < 0 ) {
if ( noGui )
printf ( " exportmp3: error from encoder: %ld \n " , bytes ) ;
2012-05-26 14:49:10 +02:00
else {
2012-06-21 13:38:13 +02:00
QMessageBox : : warning ( 0 ,
tr ( " Encoding error " ) ,
tr ( " Error %1 returned from MP3 encoder " ) . arg ( bytes ) ,
QString : : null , QString : : null ) ;
2012-05-26 14:49:10 +02:00
break ;
}
2012-06-21 13:38:13 +02:00
}
else
file . write ( ( char * ) bufferOut , bytes ) ;
2012-05-26 14:49:10 +02:00
}
else {
for ( int i = 0 ; i < FRAMES ; + + i ) {
2012-06-21 13:38:13 +02:00
peak = qMax ( peak , qAbs ( bufferL [ i ] ) ) ;
peak = qMax ( peak , qAbs ( bufferR [ i ] ) ) ;
2012-05-26 14:49:10 +02:00
}
}
playTime = endTime ;
pBar - > setValue ( int ( playTime ) ) ;
if ( playTime > et )
break ;
}
gain = 0.99 / peak ;
}
2012-06-21 13:38:13 +02:00
long bytes = exporter . finishStream ( bufferOut ) ;
if ( bytes > 0L )
file . write ( ( char * ) bufferOut , bytes ) ;
2012-05-26 14:49:10 +02:00
hideProgressBar ( ) ;
delete synti ;
delete bufferOut ;
file . close ( ) ;
2012-06-21 13:38:13 +02:00
MScore : : sampleRate = oldSampleRate ;
2012-05-26 14:49:10 +02:00
return true ;
}