Need some virtual in AudioFormat derived classes


#1

Hello

I would like to use FLAC and OGG AudioFormat classes for encoding/transcoding purposes. Since the writer classes for those formats are quite basic (I need to implement quality options and metadata writing), I’d like to derive those classes and re-implement a few methods. Would it be possible to keep the virtual attribute of AudioFormat’s methods AudioFormat derived classes?
Rather than copying the source code, I’d prefer having my new classes inheriting OGG and FLAC Audioformat for easier code maintenance when updating the Juce library…

Thanks


#2

Quality settings are something that should go into the library, really - if you want to suggest any changes, I’d be happy to consider adding it to the library. It’d probably be pretty easy to add.

I don’t understand what you mean by this.


#3

I mean, keeping the virtual attributes for createWriterFor, createReaderFor, … implemented by various AudioFormat classes (OggVorbisAudioFormat, FLACVorbisAudioFormat,… ).
Tell me if I’m wrong but, for instance: if I create a new OggVorbisAudioFormat2, inheriting OggVorbisAudioFormat, a new Vtable entry will created for a new implementation of OggVorbisAudioFormat2::createWriterFor() method, instead of replacing the OggVorbisAudioFormat::createWriterFor()'s one, which would have been the case if OggVorbisAudioFormat::createWriterFor() had virtual attribute. The drawback being that if I use an OggVorbisAudioFormat2 through an OggVorbisAudioFormat pointer, calling createWriterFor() method on this pointer will call OggVorbisAudioFormat::createWriterFor()… no more polymorphism…


#4

… about quality I just think about adding 0-8 compression level handling for FLAC, just like the FLAC encoder command line application does.


#5

Yes, you’re wrong. It seems like quite a common mistake to not realise that there’s no need to add the virtual keyword if a method is already virtual. You can’t un-virtualise it!


#6

ok cool, I feel smarter now :slight_smile:

Thanks


#7

Hi

May I suggest the following changes in juce_FLACAudioFormat.cpp though?

New int QualityOptionIndex parameter in FlacWriter:

[code]FlacWriter ( OutputStream* const out,
const double sampleRate_,
const int numChannels_,
const int bitsPerSample_,
const int qualityOptionIndex = 5)
: AudioFormatWriter (out, TRANS (flacFormatName),
sampleRate_,
numChannels_,
bitsPerSample_)
{
using namespace FlacNamespace;
encoder = FLAC__stream_encoder_new();

	FLAC__stream_encoder_set_compression_level(encoder, jlimit(0, 8, qualityOptionIndex));

	FLAC__stream_encoder_set_channels (encoder, numChannels);

[/code]

and, accordingly, in FlacAudioFormat::createWriterFor() … :

[code]AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
double sampleRate,
unsigned int numberOfChannels,
int bitsPerSample,
const StringPairArray& /metadataValues/,
int qualityOptionIndex)
{
if (getPossibleBitDepths().contains (bitsPerSample))
{
ScopedPointer w (new FlacWriter (out, sampleRate, numberOfChannels, bitsPerSample, qualityOptionIndex));

    if (w->ok)
        return w.release();
}

return 0;

}
[/code]

It just adds quality settings (compression level actually) handling, instead of always using the 5th level.

Cheers


#8

Seems reasonable, though it’d need to be a bit smarter so that code which passes 0 as the quality will still use the default level. I’ll add that when I get a moment, thanks!