1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-04-13 12:31:52 +02:00

* Now supports FLAC playback.

This commit is contained in:
Christian Muehlhaeuser 2010-11-25 11:12:12 +01:00
parent 484cab1553
commit ebca511e43
10 changed files with 241 additions and 87 deletions

View File

@ -38,6 +38,7 @@ SET( tomahawkSources ${tomahawkSources}
audio/madtranscode.cpp
audio/vorbistranscode.cpp
audio/flactranscode.cpp
audio/audioengine.cpp
utils/tomahawkutils.cpp
@ -167,6 +168,7 @@ SET( tomahawkHeaders ${tomahawkHeaders}
audio/transcodeinterface.h
audio/madtranscode.h
audio/vorbistranscode.h
audio/flactranscode.h
audio/audioengine.h
database/fuzzyindex.h

View File

@ -17,4 +17,5 @@ SET( OS_SPECIFIC_LINK_LIBRARIES
mad
vorbisfile
ogg
FLAC++
)

View File

@ -10,6 +10,9 @@
#ifndef NO_OGG
#include "vorbistranscode.h"
#endif
#ifndef NO_FLAC
#include "flactranscode.h"
#endif
AudioEngine::AudioEngine()
@ -187,6 +190,12 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
{
m_transcode = QSharedPointer<TranscodeInterface>(new VorbisTranscode());
}
#endif
#ifndef NO_FLAC
else if ( m_currentTrack->mimetype() == "audio/flac" )
{
m_transcode = QSharedPointer<TranscodeInterface>(new FLACTranscode());
}
#endif
else
qDebug() << "Could NOT find suitable transcoder! Stopping audio.";

150
src/audio/flactranscode.cpp Normal file
View File

@ -0,0 +1,150 @@
#include "flactranscode.h"
FLACTranscode::FLACTranscode()
: m_FLACInit( false )
, m_FLACRunning( false )
, m_finished( false )
{
qDebug() << Q_FUNC_INFO;
init();
}
FLACTranscode::~FLACTranscode()
{
qDebug() << Q_FUNC_INFO;
}
void
FLACTranscode::onSeek( int seconds )
{
QMutexLocker locker( &m_mutex );
m_buffer.clear();
m_outBuffer.clear();
}
void
FLACTranscode::clearBuffers()
{
QMutexLocker locker( &m_mutex );
m_FLACInit = false;
m_FLACRunning = false;
m_finished = false;
m_buffer.clear();
m_outBuffer.clear();
flush();
reset();
}
void
FLACTranscode::processData( const QByteArray& data, bool finish )
{
m_mutex.lock();
m_buffer.append( data );
m_mutex.unlock();
if ( !m_FLACInit && m_buffer.size() > FLAC_BUFFER )
{
m_FLACInit = true;
set_metadata_respond_all();
process_single();
}
while ( m_buffer.size() > FLAC_BUFFER / 2 )
{
process_single();
}
m_finished = finish;
}
::FLAC__StreamDecoderReadStatus
FLACTranscode::read_callback( FLAC__byte buffer[], size_t *bytes )
{
QMutexLocker locker( &m_mutex );
if ( *bytes > (unsigned int)m_buffer.size() )
*bytes = m_buffer.size();
memcpy( buffer, (char*)m_buffer.data(), *bytes );
m_buffer.remove( 0, *bytes );
if ( !*bytes )
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
else
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
::FLAC__StreamDecoderWriteStatus
FLACTranscode::write_callback( const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[] )
{
union PCMDATA
{
FLAC__int32 i;
unsigned char b[2];
} pcmDataLeft, pcmDataRight;
for ( unsigned int sample = 0; sample < frame->header.blocksize; sample++ )
{
pcmDataLeft.i = buffer[0][sample];
pcmDataRight.i = buffer[1][sample];
m_outBuffer.append( pcmDataLeft.b[0] );
m_outBuffer.append( pcmDataLeft.b[1] );
m_outBuffer.append( pcmDataRight.b[0] );
m_outBuffer.append( pcmDataRight.b[1] );
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
void
FLACTranscode::metadata_callback( const ::FLAC__StreamMetadata *metadata )
{
qDebug() << Q_FUNC_INFO;
switch ( metadata->type )
{
case FLAC__METADATA_TYPE_STREAMINFO:
{
FLAC::Metadata::StreamInfo stream_info( (::FLAC__StreamMetadata *)metadata, true );
// Try to determine samplerate
qDebug() << "FLACTranscode( BitsPerSample:" << stream_info.get_bits_per_sample() << "Samplerate:" << stream_info.get_sample_rate() << "Channels:" << stream_info.get_channels() << ")";
emit streamInitialized( stream_info.get_sample_rate(), stream_info.get_channels() );
m_FLACRunning = true;
break;
}
default:
qDebug() << "Not handling type:" << metadata->type;
break;
}
}
void
FLACTranscode::error_callback( ::FLAC__StreamDecoderErrorStatus status )
{
qDebug() << Q_FUNC_INFO << status;
}
bool
FLACTranscode::eof_callback()
{
return ( m_buffer.isEmpty() && m_finished );
}

71
src/audio/flactranscode.h Normal file
View File

@ -0,0 +1,71 @@
/*! \class FLACTranscode
\brief Transcoding plugin for FLAC streams.
*/
#ifndef FLAC_TRANSCODE_H
#define FLAC_TRANSCODE_H
#include "transcodeinterface.h"
#include <FLAC/format.h>
#include <FLAC++/decoder.h>
#include <FLAC++/metadata.h>
#include <QObject>
#include <QMutex>
#include <QDebug>
#define FLAC_BUFFER 32768
#define FLAC_BUFFER_PREFERRED 32768
class FLACTranscode : public TranscodeInterface , protected FLAC::Decoder::Stream
{
Q_OBJECT
public:
FLACTranscode();
~FLACTranscode();
const QStringList supportedTypes() const { QStringList l; l << "audio/flac" << "flac"; return l; }
int needData() { return FLAC_BUFFER - m_buffer.count(); }
bool haveData() { return !m_outBuffer.isEmpty(); }
unsigned int preferredDataSize() { return FLAC_BUFFER_PREFERRED; }
QByteArray data() { QByteArray b = m_outBuffer; m_outBuffer.clear(); return b; }
QMutex* mutex() { return &m_mutex; }
QByteArray* buffer() { return &m_buffer; }
signals:
void streamInitialized( long sampleRate, int channels );
public slots:
void onSeek( int seconds );
void clearBuffers();
void processData( const QByteArray& data, bool finish );
protected:
virtual ::FLAC__StreamDecoderReadStatus read_callback( FLAC__byte buffer[], size_t *bytes );
virtual ::FLAC__StreamDecoderWriteStatus write_callback( const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[] );
virtual bool eof_callback();
void metadata_callback( const ::FLAC__StreamMetadata *metadata );
void error_callback( ::FLAC__StreamDecoderErrorStatus status );
/* ::FLAC__StreamDecoderSeekStatus seek_callback( FLAC__uint64 absolute_byte_offset );
::FLAC__StreamDecoderTellStatus tell_callback( FLAC__uint64 *absolute_byte_offset );
::FLAC__StreamDecoderLengthStatus length_callback( FLAC__uint64 *stream_length );*/
private:
QByteArray m_outBuffer;
QMutex m_mutex;
QByteArray m_buffer;
bool m_FLACInit;
bool m_FLACRunning;
bool m_finished;
};
#endif

View File

@ -1,24 +1,3 @@
/***************************************************************************
* Copyright (C) 2005 - 2007 by *
* Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> *
* Erik Jaelevik, Last.fm Ltd <erik@last.fm> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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., *
* 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "madtranscode.h"
#include <QDebug>

View File

@ -1,23 +1,3 @@
/***************************************************************************
* Copyright (C) 2005 - 2007 by *
* Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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., *
* 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*! \class MadTranscode
\brief Transcoding plugin for MP3 streams, using libmad.
*/

View File

@ -1,23 +1,3 @@
/***************************************************************************
* Copyright (C) 2005 - 2006 by *
* Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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., *
* 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "vorbistranscode.h"

View File

@ -1,23 +1,3 @@
/***************************************************************************
* Copyright (C) 2005 - 2006 by *
* Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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., *
* 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*! \class VorbisTranscode
\brief Transcoding plugin for OGG/Vorbis streams.
*/

View File

@ -17,15 +17,17 @@ MusicScanner::MusicScanner( const QString& dir, quint32 bs )
m_ext2mime.insert( "mp3", "audio/mpeg" );
#ifndef NO_OGG
m_ext2mime.insert( "ogg", "application/ogg" );
#endif
#ifndef NO_FLAC
m_ext2mime.insert( "flac", "audio/flac" );
#endif
// m_ext2mime.insert( "aac", "audio/mp4" );
// m_ext2mime.insert( "m4a", "audio/mp4" );
// m_ext2mime.insert( "mp4", "audio/mp4" );
// m_ext2mime.insert( "flac", "audio/flac" );
#ifndef NO_OGG
// not compiled on windows yet
m_ext2mime.insert( "ogg", "application/ogg" );
#endif
}