diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-03 02:15:56 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-03 02:15:56 +0000 |
commit | 50b48aec6ddd451a6d1709c0942477b503457663 (patch) | |
tree | a9ece53ec06fd0a2819de7a2a6de997193566626 /plugins/encoder/ogg | |
download | k3b-50b48aec6ddd451a6d1709c0942477b503457663.tar.gz k3b-50b48aec6ddd451a6d1709c0942477b503457663.zip |
Added abandoned KDE3 version of K3B
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k3b@1084400 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'plugins/encoder/ogg')
-rw-r--r-- | plugins/encoder/ogg/Makefile.am | 13 | ||||
-rw-r--r-- | plugins/encoder/ogg/base_k3boggvorbisencodersettingswidget.ui | 392 | ||||
-rw-r--r-- | plugins/encoder/ogg/k3boggvorbisencoder.cpp | 555 | ||||
-rw-r--r-- | plugins/encoder/ogg/k3boggvorbisencoder.h | 81 | ||||
-rw-r--r-- | plugins/encoder/ogg/k3boggvorbisencoder.plugin | 9 |
5 files changed, 1050 insertions, 0 deletions
diff --git a/plugins/encoder/ogg/Makefile.am b/plugins/encoder/ogg/Makefile.am new file mode 100644 index 0000000..712adbb --- /dev/null +++ b/plugins/encoder/ogg/Makefile.am @@ -0,0 +1,13 @@ +AM_CPPFLAGS = -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3b/plugin -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3bdevice $(all_includes) + +kde_module_LTLIBRARIES = libk3boggvorbisencoder.la + +libk3boggvorbisencoder_la_SOURCES = base_k3boggvorbisencodersettingswidget.ui k3boggvorbisencoder.cpp + +libk3boggvorbisencoder_la_LIBADD = ../../../libk3b/libk3b.la $(LIB_KDECORE) -logg -lvorbis -lvorbisenc +libk3boggvorbisencoder_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries) + +pluginsdir = $(kde_datadir)/k3b/plugins +plugins_DATA = k3boggvorbisencoder.plugin + +METASOURCES = AUTO diff --git a/plugins/encoder/ogg/base_k3boggvorbisencodersettingswidget.ui b/plugins/encoder/ogg/base_k3boggvorbisencodersettingswidget.ui new file mode 100644 index 0000000..3e31265 --- /dev/null +++ b/plugins/encoder/ogg/base_k3boggvorbisencodersettingswidget.ui @@ -0,0 +1,392 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>base_K3bOggVorbisEncoderSettingsWidget</class> +<author>Sebastian Trueg</author> +<widget class="QWidget"> + <property name="name"> + <cstring>Form1</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>335</width> + <height>271</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>buttonGroup1</cstring> + </property> + <property name="title"> + <string>File Quality</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_radioQualityLevel</cstring> + </property> + <property name="text"> + <string>&Quality level:</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Controls the quality of the encoded files</string> + </property> + <property name="whatsThis" stdset="0"> + <string><p>Vorbis' audio quality is not best measured in kilobits per second, but on a scale from -1 to 10 called "quality". <p>For now, quality -1 is roughly equivalent to 45kbps average, 5 is roughly 160kbps, and 10 gives about 400kbps. Most people seeking very-near-CD-quality audio encode at a quality of 5 or, for lossless stereo coupling, 6. The default setting is quality 3, which at approximately 110kbps gives a smaller filesize and significantly better fidelity than .mp3 compression at 128kbps. <p><em>This explanation was copied from the www.vorbis.com FAQ.</em></string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>m_labelQualityLevel</cstring> + </property> + <property name="font"> + <font> + <bold>1</bold> + </font> + </property> + <property name="text"> + <string>textLabel1</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </hbox> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>frame6</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <spacer> + <property name="name"> + <cstring>spacer2_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSlider" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>m_slideQualityLevel</cstring> + </property> + <property name="minValue"> + <number>-1</number> + </property> + <property name="maxValue"> + <number>10</number> + </property> + <property name="pageStep"> + <number>3</number> + </property> + <property name="value"> + <number>3</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="font"> + <font> + <italic>1</italic> + </font> + </property> + <property name="text"> + <string>high quality</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel3_2</cstring> + </property> + <property name="font"> + <font> + <italic>1</italic> + </font> + </property> + <property name="text"> + <string>small file</string> + </property> + </widget> + </grid> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer9</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QRadioButton"> + <property name="name"> + <cstring>m_radioManual</cstring> + </property> + <property name="text"> + <string>M&anual settings:</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QFrame"> + <property name="name"> + <cstring>frame3</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>m_checkBitrateUpper</cstring> + </property> + <property name="text"> + <string>&Upper bitrate:</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>m_checkBitrateLower</cstring> + </property> + <property name="text"> + <string>Lower &bitrate:</string> + </property> + </widget> + <widget class="KIntNumInput" row="0" column="1"> + <property name="name"> + <cstring>m_inputBitrateUpper</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="KIntNumInput" row="1" column="1"> + <property name="name"> + <cstring>m_inputBitrateNominal</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="KIntNumInput" row="2" column="1"> + <property name="name"> + <cstring>m_inputBitrateLower</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>kbps</string> + </property> + </widget> + <widget class="QLabel" row="2" column="2"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>kbps</string> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>kbps</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>m_checkBitrateNominal</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Nominal bitrate:</string> + </property> + </widget> + </grid> + </widget> + </hbox> + </widget> + </vbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_radioManual</sender> + <signal>toggled(bool)</signal> + <receiver>frame3</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_checkBitrateUpper</sender> + <signal>toggled(bool)</signal> + <receiver>m_inputBitrateUpper</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_checkBitrateNominal</sender> + <signal>toggled(bool)</signal> + <receiver>m_inputBitrateNominal</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_checkBitrateLower</sender> + <signal>toggled(bool)</signal> + <receiver>m_inputBitrateLower</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_radioQualityLevel</sender> + <signal>toggled(bool)</signal> + <receiver>m_labelQualityLevel</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>m_radioQualityLevel</sender> + <signal>toggled(bool)</signal> + <receiver>frame6</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/plugins/encoder/ogg/k3boggvorbisencoder.cpp b/plugins/encoder/ogg/k3boggvorbisencoder.cpp new file mode 100644 index 0000000..54e6ecb --- /dev/null +++ b/plugins/encoder/ogg/k3boggvorbisencoder.cpp @@ -0,0 +1,555 @@ +/* + * + * $Id: k3boggvorbisencoder.cpp 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * 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. + * See the file "COPYING" for the exact licensing terms. + */ + +#include <config.h> + +#include "k3boggvorbisencoder.h" +#include "base_k3boggvorbisencodersettingswidget.h" + +#include <k3bcore.h> +#include <k3bpluginfactory.h> + +#include <klocale.h> +#include <kconfig.h> +#include <kdebug.h> +#include <knuminput.h> + +#include <qlayout.h> +#include <qradiobutton.h> +#include <qslider.h> +#include <qlcdnumber.h> +#include <qcheckbox.h> +#include <qcstring.h> +#include <qtooltip.h> +#include <qwhatsthis.h> +#include <qlabel.h> + +#include <vorbis/vorbisenc.h> + +// for the random generator +#include <stdlib.h> +#include <time.h> + + +K_EXPORT_COMPONENT_FACTORY( libk3boggvorbisencoder, K3bPluginFactory<K3bOggVorbisEncoder>( "libk3boggvorbisencoder" ) ) + +// quality levels -1 to 10 map to 0 to 11 +static const int s_rough_average_quality_level_bitrates[] = { + 45, + 64, + 80, + 96, + 112, + 128, + 160, + 192, + 224, + 256, + 320, + 400 +}; + +// quality levels -1 to 10 map to 0 to 11 +// static const char* s_ogg_quality_level_strings[] = { +// I18N_NOOP("Low quality"), +// I18N_NOOP(""), +// I18N_NOOP(""), +// I18N_NOOP(""), +// I18N_NOOP(""), +// I18N_NOOP("targetted %1 kbps"), +// I18N_NOOP("targetted %1 kbps"), +// I18N_NOOP("targetted %1 kbps"), +// I18N_NOOP(""), +// I18N_NOOP(""), +// I18N_NOOP(""), +// I18N_NOOP(""), +// }; + + +// THIS IS BASED ON THE OGG VORBIS LIB EXAMPLE +// BECAUSE OF THE LACK OF DOCUMENTATION + + +class K3bOggVorbisEncoder::Private +{ +public: + Private() + : manualBitrate(false), + qualityLevel(4), + bitrateUpper(-1), + bitrateNominal(-1), + bitrateLower(-1), + // sampleRate(44100), + oggStream(0), + oggPage(0), + oggPacket(0), + vorbisInfo(0), + vorbisComment(0), + vorbisDspState(0), + vorbisBlock(0), + headersWritten(false) { + } + + // encoding settings + bool manualBitrate; + // 0 to 10 -> 0.0 - 1.0 + int qualityLevel; + int bitrateUpper; + int bitrateNominal; + int bitrateLower; + // int sampleRate; + + // encoding structures + ogg_stream_state *oggStream; // take physical pages, weld into a logical stream of packets + ogg_page *oggPage; // one Ogg bitstream page. Vorbis packets are inside + ogg_packet *oggPacket; // one raw packet of data for decode + vorbis_info *vorbisInfo; // struct that stores all the static vorbis bitstream settings + vorbis_comment *vorbisComment; // struct that stores all the user comments + vorbis_dsp_state *vorbisDspState; // central working state for the packet->PCM decoder + vorbis_block *vorbisBlock; // local working space for packet->PCM decode + + bool headersWritten; +}; + + +K3bOggVorbisEncoder::K3bOggVorbisEncoder( QObject* parent, const char* name ) + : K3bAudioEncoder( parent, name ) +{ + d = new Private(); +} + + +K3bOggVorbisEncoder::~K3bOggVorbisEncoder() +{ + cleanup(); + delete d; +} + + +bool K3bOggVorbisEncoder::initEncoderInternal( const QString&, const K3b::Msf& ) +{ + cleanup(); + + // load user settings + loadConfig(); + + d->oggPage = new ogg_page; + d->oggPacket = new ogg_packet; + d->vorbisInfo = new vorbis_info; + + vorbis_info_init( d->vorbisInfo ); + + int ret = 0; + + if( d->manualBitrate ) { + kdDebug() << "(K3bOggVorbisEncoder) calling: " + << "vorbis_encode_init( d->vorbisInfo, 2, 44100, " + << (d->bitrateUpper != -1 ? d->bitrateUpper*1000 : -1) << ", " + << (d->bitrateNominal != -1 ? d->bitrateNominal*1000 : -1) << ", " + << (d->bitrateLower != -1 ? d->bitrateLower*1000 : -1) << " );" << endl; + + ret = vorbis_encode_init( d->vorbisInfo, + 2, // 2 channels: stereo + 44100, + d->bitrateUpper != -1 ? d->bitrateUpper*1000 : -1, + d->bitrateNominal != -1 ? d->bitrateNominal*1000 : -1, + d->bitrateLower != -1 ? d->bitrateLower*1000 : -1 ); + } + else { + if( d->qualityLevel < -1 ) + d->qualityLevel = -1; + else if( d->qualityLevel > 10 ) + d->qualityLevel = 10; + + kdDebug() << "(K3bOggVorbisEncoder) calling: " + << "vorbis_encode_init_vbr( d->vorbisInfo, 2, 44100, " + << (float)d->qualityLevel/10.0 << ");" << endl; + + ret = vorbis_encode_init_vbr( d->vorbisInfo, + 2, // 2 channels: stereo + 44100, + (float)d->qualityLevel/10.0 ); + } + + if( ret ) { + kdDebug() << "(K3bOggVorbisEncoder) vorbis_encode_init failed: " << ret << endl; + cleanup(); + return false; + } + + // init the comment stuff + d->vorbisComment = new vorbis_comment; + vorbis_comment_init( d->vorbisComment ); + + // add the encoder tag (so everybody knows we did it! ;) + vorbis_comment_add_tag( d->vorbisComment, QCString("ENCODER").data(), QCString("K3bOggVorbisEncoderPlugin").data() ); + + // set up the analysis state and auxiliary encoding storage + d->vorbisDspState = new vorbis_dsp_state; + d->vorbisBlock = new vorbis_block; + vorbis_analysis_init( d->vorbisDspState, d->vorbisInfo ); + vorbis_block_init( d->vorbisDspState, d->vorbisBlock ); + + // set up our packet->stream encoder + // pick a random serial number; that way we can more likely build + // chained streams just by concatenation + d->oggStream = new ogg_stream_state; + srand( time(0) ); + ogg_stream_init( d->oggStream, rand() ); + + return true; +} + + +bool K3bOggVorbisEncoder::writeOggHeaders() +{ + if( !d->oggStream ) { + kdDebug() << "(K3bOggVorbisEncoder) call to writeOggHeaders without init." << endl; + return false; + } + if( d->headersWritten ) { + kdDebug() << "(K3bOggVorbisEncoder) headers already written." << endl; + return true; + } + + // + // Vorbis streams begin with three headers; the initial header (with + // most of the codec setup parameters) which is mandated by the Ogg + // bitstream spec. The second header holds any comment fields. The + // third header holds the bitstream codebook. We merely need to + // make the headers, then pass them to libvorbis one at a time; + // libvorbis handles the additional Ogg bitstream constraints + // + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout( d->vorbisDspState, + d->vorbisComment, + &header, + &header_comm, + &header_code); + + // automatically placed in its own page + ogg_stream_packetin( d->oggStream, &header ); + ogg_stream_packetin( d->oggStream, &header_comm ); + ogg_stream_packetin( d->oggStream, &header_code ); + + // + // This ensures the actual + // audio data will start on a new page, as per spec + // + QByteArray data; + while( ogg_stream_flush( d->oggStream, d->oggPage ) ) { + writeData( (char*)d->oggPage->header, d->oggPage->header_len ); + writeData( (char*)d->oggPage->body, d->oggPage->body_len ); + } + + d->headersWritten = true; + + return true; +} + + +long K3bOggVorbisEncoder::encodeInternal( const char* data, Q_ULONG len ) +{ + if( !d->headersWritten ) + if( !writeOggHeaders() ) + return -1; + + // expose the buffer to submit data + float** buffer = vorbis_analysis_buffer( d->vorbisDspState, len/4 ); + + // uninterleave samples + unsigned long i = 0; + for( i = 0; i < len/4; i++ ) { + buffer[0][i]=( (data[i*4+1]<<8) | (0x00ff&(int)data[i*4]) ) / 32768.f; + buffer[1][i]=( (data[i*4+3]<<8) | (0x00ff&(int)data[i*4+2]) ) / 32768.f; + } + + // tell the library how much we actually submitted + vorbis_analysis_wrote( d->vorbisDspState, i ); + + return flushVorbis(); +} + + +long K3bOggVorbisEncoder::flushVorbis() +{ + // vorbis does some data preanalysis, then divvies up blocks for + // more involved (potentially parallel) processing. Get a single + // block for encoding now + long writtenData = 0; + while( vorbis_analysis_blockout( d->vorbisDspState, d->vorbisBlock ) == 1 ) { + + // analysis + vorbis_analysis( d->vorbisBlock, 0 ); + vorbis_bitrate_addblock( d->vorbisBlock ); + + while( vorbis_bitrate_flushpacket( d->vorbisDspState, d->oggPacket ) ) { + + // weld the packet into the bitstream + ogg_stream_packetin( d->oggStream, d->oggPacket ); + + // write out pages (if any) + while( ogg_stream_pageout( d->oggStream, d->oggPage ) ) { + writeData( (char*)d->oggPage->header, d->oggPage->header_len ); + writeData( (char*)d->oggPage->body, d->oggPage->body_len ); + + writtenData += ( d->oggPage->header_len + d->oggPage->body_len ); + } + } + } + + return writtenData; +} + + +void K3bOggVorbisEncoder::finishEncoderInternal() +{ + if( d->vorbisDspState ) { + vorbis_analysis_wrote( d->vorbisDspState, 0 ); + flushVorbis(); + } + else + kdDebug() << "(K3bOggVorbisEncoder) call to finishEncoderInternal without init." << endl; +} + + +void K3bOggVorbisEncoder::setMetaDataInternal( K3bAudioEncoder::MetaDataField f, const QString& value ) +{ + if( d->vorbisComment ) { + QCString key; + + switch( f ) { + case META_TRACK_TITLE: + key = "TITLE"; + break; + case META_TRACK_ARTIST: + key = "ARTIST"; + break; + case META_ALBUM_TITLE: + key = "ALBUM"; + break; + case META_ALBUM_COMMENT: + key = "DESCRIPTION"; + break; + case META_YEAR: + key = "DATE"; + break; + case META_TRACK_NUMBER: + key = "TRACKNUMBER"; + break; + case META_GENRE: + key = "GENRE"; + break; + default: + return; + } + + vorbis_comment_add_tag( d->vorbisComment, key.data(), value.utf8().data() ); + } + else + kdDebug() << "(K3bOggVorbisEncoder) call to setMetaDataInternal without init." << endl; +} + + +void K3bOggVorbisEncoder::cleanup() +{ + if( d->oggStream ) { + ogg_stream_clear( d->oggStream ); + delete d->oggStream; + d->oggStream = 0; + } + if( d->vorbisBlock ) { + vorbis_block_clear( d->vorbisBlock ); + delete d->vorbisBlock; + d->vorbisBlock = 0; + } + if( d->vorbisDspState ) { + vorbis_dsp_clear( d->vorbisDspState ); + delete d->vorbisDspState; + d->vorbisDspState = 0; + } + if( d->vorbisComment ) { + vorbis_comment_clear( d->vorbisComment ); + delete d->vorbisComment; + d->vorbisComment = 0; + } + if( d->vorbisInfo ) { + vorbis_info_clear( d->vorbisInfo ); + delete d->vorbisInfo; + d->vorbisInfo = 0; + } + + // ogg_page and ogg_packet structs always point to storage in + // libvorbis. They're never freed or manipulated directly + if( d->oggPage ) { + delete d->oggPage; + d->oggPage = 0; + } + if( d->oggPacket ) { + delete d->oggPacket; + d->oggPacket = 0; + } + + d->headersWritten = false; +} + + +void K3bOggVorbisEncoder::loadConfig() +{ + KConfig* c = k3bcore->config(); + + c->setGroup( "K3bOggVorbisEncoderPlugin" ); + + d->manualBitrate = c->readBoolEntry( "manual bitrate", false ); + d->qualityLevel = c->readNumEntry( "quality level", 4 ); + d->bitrateUpper = c->readNumEntry( "bitrate upper", -1 ); + d->bitrateNominal = c->readNumEntry( "bitrate nominal", -1 ); + d->bitrateLower = c->readNumEntry( "bitrate lower", -1 ); + // d->sampleRate = c->readNumEntry( "samplerate", 44100 ); +} + + + + +K3bOggVorbisEncoderSettingsWidget::K3bOggVorbisEncoderSettingsWidget( QWidget* parent, const char* name ) + : K3bPluginConfigWidget( parent, name ) +{ + w = new base_K3bOggVorbisEncoderSettingsWidget( this ); + + QString ttQuality = i18n("Controls the quality of the encoded files."); + QString wsQuality = i18n("<p>Vorbis' audio quality is not best measured in kilobits per second, " + "but on a scale from -1 to 10 called <em>quality</em>." + "<p>For now, quality -1 is roughly equivalent to 45kbps average, " + "5 is roughly 160kbps, and 10 gives about 400kbps. " + "Most people seeking very-near-CD-quality audio encode at a quality of 5 or, " + "for lossless stereo coupling, 6. The quality 3 gives, at " + "approximately 110kbps a smaller filesize and significantly better fidelity " + "than .mp3 compression at 128kbps." + "<p><em>This explanation is based on the one from the www.vorbis.com FAQ.</em>"); + + QToolTip::add( w->m_radioQualityLevel, ttQuality ); + QToolTip::add( w->m_labelQualityLevel, ttQuality ); + QToolTip::add( w->m_slideQualityLevel, ttQuality ); + QWhatsThis::add( w->m_radioQualityLevel, wsQuality ); + QWhatsThis::add( w->m_labelQualityLevel, wsQuality ); + QWhatsThis::add( w->m_slideQualityLevel, wsQuality ); + + + QHBoxLayout* lay = new QHBoxLayout( this ); + lay->setMargin( 0 ); + + lay->addWidget( w ); + + connect( w->m_slideQualityLevel, SIGNAL(valueChanged(int)), + this, SLOT(slotQualityLevelChanged(int)) ); + + slotQualityLevelChanged( 4 ); +} + + +K3bOggVorbisEncoderSettingsWidget::~K3bOggVorbisEncoderSettingsWidget() +{ +} + + +void K3bOggVorbisEncoderSettingsWidget::slotQualityLevelChanged( int val ) +{ + w->m_labelQualityLevel->setText( QString::number(val) + " " + + i18n("(targetted VBR of %1)").arg(s_rough_average_quality_level_bitrates[val+1]) ); +} + + +void K3bOggVorbisEncoderSettingsWidget::loadConfig() +{ + KConfig* c = k3bcore->config(); + + c->setGroup( "K3bOggVorbisEncoderPlugin" ); + + if( c->readBoolEntry( "manual bitrate", false ) ) + w->m_radioManual->setChecked(true); + else + w->m_radioQualityLevel->setChecked(true); + w->m_slideQualityLevel->setValue( c->readNumEntry( "quality level", 4 ) ); + w->m_inputBitrateUpper->setValue( c->readNumEntry( "bitrate upper", -1 ) ); + w->m_checkBitrateUpper->setChecked( c->readNumEntry( "bitrate upper", -1 ) != -1 ); + w->m_inputBitrateNominal->setValue( c->readNumEntry( "bitrate nominal", -1 ) ); + w->m_checkBitrateNominal->setChecked( c->readNumEntry( "bitrate nominal", -1 ) != -1 ); + w->m_inputBitrateLower->setValue( c->readNumEntry( "bitrate lower", -1 ) ); + w->m_checkBitrateLower->setChecked( c->readNumEntry( "bitrate lower", -1 ) != -1 ); + // w->m_inputSamplerate->setValue( c->readNumEntry( "samplerate", 44100 ) ); +} + + +void K3bOggVorbisEncoderSettingsWidget::saveConfig() +{ + KConfig* c = k3bcore->config(); + + c->setGroup( "K3bOggVorbisEncoderPlugin" ); + + c->writeEntry( "manual bitrate", w->m_radioManual->isChecked() ); + c->writeEntry( "quality level", w->m_slideQualityLevel->value() ); + c->writeEntry( "bitrate upper", w->m_checkBitrateUpper->isChecked() ? w->m_inputBitrateUpper->value() : -1 ); + c->writeEntry( "bitrate nominal", w->m_checkBitrateNominal->isChecked() ? w->m_inputBitrateNominal->value() : -1 ); + c->writeEntry( "bitrate lower", w->m_checkBitrateLower->isChecked() ? w->m_inputBitrateLower->value() : -1 ); + // c->writeEntry( "samplerate", w->m_inputSamplerate->value() ); +} + + +QString K3bOggVorbisEncoder::fileTypeComment( const QString& ) const +{ + return i18n("Ogg-Vorbis"); +} + + +long long K3bOggVorbisEncoder::fileSize( const QString&, const K3b::Msf& msf ) const +{ + KConfig* c = k3bcore->config(); + c->setGroup( "K3bOggVorbisEncoderPlugin" ); + + // the following code is based on the size estimation from the audiocd kioslave + // TODO: reimplement. + + if( !c->readBoolEntry( "manual bitrate", false ) ) { + // Estimated numbers based on the Vorbis FAQ: + // http://www.xiph.org/archives/vorbis-faq/200203/0030.html + +// static long vorbis_q_bitrate[] = { 45, 60, 74, 86, 106, 120, 152, +// 183, 207, 239, 309, 440 }; + + int qualityLevel = c->readNumEntry( "quality level", 4 ); + + if( qualityLevel < -1 ) + qualityLevel = -1; + else if( qualityLevel > 10 ) + qualityLevel = 10; + return ( (msf.totalFrames()/75) * s_rough_average_quality_level_bitrates[qualityLevel+1] * 1000 ) / 8; + } + else { + return (msf.totalFrames()/75) * c->readNumEntry( "bitrate nominal", 160 ) * 1000 / 8; + } +} + + +K3bPluginConfigWidget* K3bOggVorbisEncoder::createConfigWidget( QWidget* parent, + const char* name ) const +{ + return new K3bOggVorbisEncoderSettingsWidget( parent, name ); +} + + +#include "k3boggvorbisencoder.moc" diff --git a/plugins/encoder/ogg/k3boggvorbisencoder.h b/plugins/encoder/ogg/k3boggvorbisencoder.h new file mode 100644 index 0000000..0148713 --- /dev/null +++ b/plugins/encoder/ogg/k3boggvorbisencoder.h @@ -0,0 +1,81 @@ +/* + * + * $Id: k3boggvorbisencoder.h 619556 2007-01-03 17:38:12Z trueg $ + * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org> + * + * 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. + * See the file "COPYING" for the exact licensing terms. + */ + +#ifndef _K3B_OGG_VORBIS_ENCODER_H_ +#define _K3B_OGG_VORBIS_ENCODER_H_ + + +#include <k3baudioencoder.h> +#include <k3bpluginconfigwidget.h> + + +class base_K3bOggVorbisEncoderSettingsWidget; + + +class K3bOggVorbisEncoder : public K3bAudioEncoder +{ + Q_OBJECT + + public: + K3bOggVorbisEncoder( QObject* parent = 0, const char* name = 0 ); + ~K3bOggVorbisEncoder(); + + QStringList extensions() const { return QStringList("ogg"); } + + QString fileTypeComment( const QString& ) const; + + long long fileSize( const QString&, const K3b::Msf& msf ) const; + + int pluginSystemVersion() const { return 3; } + + K3bPluginConfigWidget* createConfigWidget( QWidget* parent = 0, + const char* name = 0 ) const; + + private: + void loadConfig(); + void finishEncoderInternal(); + bool initEncoderInternal( const QString& extension, const K3b::Msf& length ); + long encodeInternal( const char* data, Q_ULONG len ); + void setMetaDataInternal( MetaDataField, const QString& ); + + bool writeOggHeaders(); + void cleanup(); + long flushVorbis(); + + class Private; + Private* d; +}; + + +class K3bOggVorbisEncoderSettingsWidget : public K3bPluginConfigWidget +{ + Q_OBJECT + + public: + K3bOggVorbisEncoderSettingsWidget( QWidget* parent = 0, const char* name = 0 ); + ~K3bOggVorbisEncoderSettingsWidget(); + + public slots: + void loadConfig(); + void saveConfig(); + + private slots: + void slotQualityLevelChanged( int val ); + + private: + base_K3bOggVorbisEncoderSettingsWidget* w; +}; + +#endif diff --git a/plugins/encoder/ogg/k3boggvorbisencoder.plugin b/plugins/encoder/ogg/k3boggvorbisencoder.plugin new file mode 100644 index 0000000..2f73e8e --- /dev/null +++ b/plugins/encoder/ogg/k3boggvorbisencoder.plugin @@ -0,0 +1,9 @@ +[K3b Plugin] +Lib=libk3boggvorbisencoder +Group=AudioEncoder +Name=K3b Ogg Vorbis Encoder +Author=Sebastian Trueg +Email=trueg@k3b.org +Version=2.1 +Comment=Encoding module to encode Ogg Vorbis files +License=GPL |