simple flac to mp3 conversion
This commit is contained in:
parent
c72269f77a
commit
7cea7ed30b
@ -19,6 +19,7 @@ add_executable(mlc
|
||||
main.cpp
|
||||
help.cpp
|
||||
decoded.cpp
|
||||
flactomp3.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(mlc
|
||||
|
150
flactomp3.cpp
Normal file
150
flactomp3.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "flactomp3.h"
|
||||
|
||||
constexpr uint16_t flacBlockMaxSize = 4096;
|
||||
|
||||
FLACtoMP3::FLACtoMP3(uint8_t size) :
|
||||
inPath(),
|
||||
outPath(),
|
||||
decoder(FLAC__stream_decoder_new()),
|
||||
encoder(lame_init()),
|
||||
statusFLAC(),
|
||||
output(),
|
||||
pcmCounter(0),
|
||||
pcmSize(size * flacBlockMaxSize),
|
||||
pcm(new int16_t[pcmSize * 2]),
|
||||
mp3(new uint8_t[pcmSize])
|
||||
{
|
||||
}
|
||||
|
||||
FLACtoMP3::~FLACtoMP3() {
|
||||
lame_close(encoder);
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
delete[] pcm;
|
||||
delete[] mp3;
|
||||
}
|
||||
|
||||
void FLACtoMP3::run() {
|
||||
FLAC__bool ok = FLAC__stream_decoder_process_until_end_of_stream(decoder);
|
||||
std::cout << "decoding: ";
|
||||
if (ok)
|
||||
std::cout << "succeeded";
|
||||
else
|
||||
std::cout << "FAILED";
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << " state: " << FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(decoder)] << std::endl;
|
||||
|
||||
flush();
|
||||
int nwrite = lame_encode_flush(encoder, mp3, pcmSize);
|
||||
output.write((char*)mp3, nwrite);
|
||||
|
||||
// // 7. Write INFO tag (OPTIONAL)
|
||||
// // lame_mp3_tags_fid(lame, mp3);
|
||||
output.close();
|
||||
}
|
||||
|
||||
void FLACtoMP3::setInputFile(const std::string& path) {
|
||||
if (inPath.size() > 0)
|
||||
throw 1;
|
||||
|
||||
inPath = path;
|
||||
|
||||
FLAC__stream_decoder_set_md5_checking(decoder, true);
|
||||
statusFLAC = FLAC__stream_decoder_init_file(decoder, path.c_str(), write, metadata, error, this);
|
||||
}
|
||||
|
||||
void FLACtoMP3::setOutputFile(const std::string& path) {
|
||||
if (outPath.size() > 0)
|
||||
throw 2;
|
||||
|
||||
outPath = path;
|
||||
|
||||
// 3. Do some settings (OPTIONAL)
|
||||
lame_set_in_samplerate(encoder, 44100);
|
||||
lame_set_VBR(encoder, vbr_default);
|
||||
lame_set_VBR_quality(encoder, 2);
|
||||
|
||||
// 4. Initialize parameters
|
||||
int ret = lame_init_params(encoder);
|
||||
if (ret < 0) {
|
||||
std::cout << "Error occurred during parameters initializing. Code = " << ret << std::endl;
|
||||
throw 3;
|
||||
}
|
||||
|
||||
output.open(path, std::ios::out | std::ios::binary);
|
||||
}
|
||||
|
||||
void FLACtoMP3::decodeFrame(const int32_t * const buffer[], uint32_t size) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
pcm[2 * pcmCounter] = (int16_t)buffer[0][i];
|
||||
pcm[2 * pcmCounter + 1] = (int16_t)buffer[1][i];
|
||||
++pcmCounter;
|
||||
}
|
||||
|
||||
if (pcmCounter == pcmSize)
|
||||
flush();
|
||||
}
|
||||
|
||||
void FLACtoMP3::flush() {
|
||||
int nwrite = lame_encode_buffer_interleaved(
|
||||
encoder,
|
||||
pcm,
|
||||
pcmCounter,
|
||||
mp3,
|
||||
pcmSize
|
||||
);
|
||||
output.write((char*)mp3, nwrite);
|
||||
pcmCounter = 0;
|
||||
}
|
||||
|
||||
void FLACtoMP3::metadata(const FLAC__StreamDecoder* decoder, const FLAC__StreamMetadata* metadata, void* client_data) {
|
||||
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderWriteStatus FLACtoMP3::write(
|
||||
const FLAC__StreamDecoder* decoder,
|
||||
const FLAC__Frame* frame,
|
||||
const FLAC__int32 * const buffer[],
|
||||
void* client_data
|
||||
){
|
||||
FLACtoMP3* self = static_cast<FLACtoMP3*>(client_data);
|
||||
self->decodeFrame(buffer, frame->header.blocksize);
|
||||
|
||||
// if (decoded->totalSamples == 0) {
|
||||
// std::cout << "ERROR: this example only works for FLAC files that have a total_samples count in STREAMINFO" << std::endl;
|
||||
// return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
// }
|
||||
// if (decoded->channels != 2 || decoded->depth != 16) {
|
||||
// std::cout << "ERROR: this example only supports 16bit stereo streams" << std::endl;
|
||||
// return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
// }
|
||||
if (frame->header.channels != 2) {
|
||||
std::cout << "ERROR: This frame contains " << frame->header.channels << " channels (should be 2)" << std::endl;
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
if (buffer[0] == NULL) {
|
||||
std::cout << "ERROR: buffer [0] is NULL" << std::endl;
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
if (buffer[1] == NULL) {
|
||||
std::cout << "ERROR: buffer [1] is NULL" << std::endl;
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
|
||||
// /* write WAVE header before we write the first frame */
|
||||
// if (frame->header.number.sample_number == 0)
|
||||
// decoded->writeWaveHeader();
|
||||
//
|
||||
// /* write decoded PCM samples */
|
||||
// for (size_t i = 0; i < frame->header.blocksize; i++) {
|
||||
// decoded->write((uint16_t)buffer[0][i]);
|
||||
// decoded->write((uint16_t)buffer[1][i]);
|
||||
// }
|
||||
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
void FLACtoMP3::error(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderErrorStatus status, void* client_data) {
|
||||
(void)decoder, (void)client_data;
|
||||
std::cout << "Got error callback: " << FLAC__StreamDecoderErrorStatusString[status] << std::endl;
|
||||
}
|
46
flactomp3.h
Normal file
46
flactomp3.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "FLAC/stream_decoder.h"
|
||||
#include <lame/lame.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <ios>
|
||||
#include <fstream>
|
||||
|
||||
class FLACtoMP3 {
|
||||
public:
|
||||
FLACtoMP3(uint8_t size = 4);
|
||||
~FLACtoMP3();
|
||||
|
||||
void setInputFile(const std::string& path);
|
||||
void setOutputFile(const std::string& path);
|
||||
void run();
|
||||
|
||||
private:
|
||||
void decodeFrame(const int32_t * const buffer[], uint32_t size);
|
||||
void flush();
|
||||
|
||||
static void error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
static void metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
|
||||
static FLAC__StreamDecoderWriteStatus write(
|
||||
const FLAC__StreamDecoder *decoder,
|
||||
const FLAC__Frame *frame,
|
||||
const FLAC__int32 * const buffer[],
|
||||
void *client_data
|
||||
);
|
||||
|
||||
private:
|
||||
std::string inPath;
|
||||
std::string outPath;
|
||||
|
||||
FLAC__StreamDecoder *decoder;
|
||||
lame_t encoder;
|
||||
FLAC__StreamDecoderInitStatus statusFLAC;
|
||||
|
||||
std::ofstream output;
|
||||
uint32_t pcmCounter;
|
||||
uint32_t pcmSize;
|
||||
int16_t* pcm;
|
||||
uint8_t* mp3;
|
||||
};
|
82
main.cpp
82
main.cpp
@ -5,7 +5,7 @@
|
||||
#include <lame/lame.h>
|
||||
|
||||
#include "help.h"
|
||||
#include "decoded.h"
|
||||
#include "flactomp3.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
@ -20,82 +20,10 @@ int main(int argc, char **argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Decoded* decoded = Decoded::fromFLACFile(firstArgument);
|
||||
decoded->saveWaveToFile("./out.wav");
|
||||
// FILE *mp3 = fopen("output.mp3", "wb");
|
||||
// size_t nread;
|
||||
// int ret, nwrite;
|
||||
//
|
||||
// // 1. Get lame version (OPTIONAL)
|
||||
// std::cout << "Using LAME v" << get_lame_version() << std::endl;
|
||||
//
|
||||
// const int PCM_SIZE = 8192;
|
||||
// const int MP3_SIZE = 8192;
|
||||
//
|
||||
// short pcm_buffer[PCM_SIZE * 2];
|
||||
// unsigned char mp3_buffer[MP3_SIZE];
|
||||
//
|
||||
// // 2. Initializing
|
||||
// lame_t lame = lame_init();
|
||||
//
|
||||
// // 3. Do some settings (OPTIONAL)
|
||||
// // lame_set_in_samplerate(lame, 48000);
|
||||
// lame_set_VBR(lame, vbr_default);
|
||||
// // lame_set_VBR_quality(lame, 2);
|
||||
//
|
||||
// // 4. Initialize parameters
|
||||
// ret = lame_init_params(lame);
|
||||
// if (ret < 0) {
|
||||
// std::cout << "Error occurred during parameters initializing. Code = " << ret << std::endl;
|
||||
// return 3;
|
||||
// }
|
||||
//
|
||||
// do {
|
||||
// // Read PCM_SIZE of array
|
||||
// nread = fread(pcm_buffer, 2 * sizeof(short), PCM_SIZE, pcm);
|
||||
// if (nread != 0) {
|
||||
// // 5. Encode
|
||||
// int nsamples = nread;
|
||||
// short buffer_l[nsamples];
|
||||
// short buffer_r[nsamples];
|
||||
//
|
||||
// printf("nread = %d\n", nread);
|
||||
// printf("pcm_buffer.length = %d\n", sizeof(pcm_buffer)/sizeof(short));
|
||||
//
|
||||
// int j = 0;
|
||||
// int i = 0;
|
||||
// for (i = 0; i < nsamples; i++) {
|
||||
// buffer_l[i] = pcm_buffer[j++];
|
||||
// buffer_r[i] = pcm_buffer[j++];
|
||||
//
|
||||
// }
|
||||
//
|
||||
// nwrite = lame_encode_buffer(lame, buffer_l, buffer_r, nread,
|
||||
// mp3_buffer, MP3_SIZE);
|
||||
// } else {
|
||||
// // 6. Flush and give some final frames
|
||||
// nwrite = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
|
||||
// }
|
||||
//
|
||||
// if (nwrite < 0) {
|
||||
// printf("Error occurred during encoding. Code = %d\n", nwrite);
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
// fwrite(mp3_buffer, nwrite, 1, mp3);
|
||||
// } while (nread != 0);
|
||||
//
|
||||
// // 7. Write INFO tag (OPTIONAL)
|
||||
// // lame_mp3_tags_fid(lame, mp3);
|
||||
//
|
||||
// // 8. Free internal data structures
|
||||
// lame_close(lame);
|
||||
//
|
||||
// fclose(mp3);
|
||||
|
||||
|
||||
|
||||
delete decoded;
|
||||
FLACtoMP3 pipe;
|
||||
pipe.setInputFile(firstArgument);
|
||||
pipe.setOutputFile("out.mp3");
|
||||
pipe.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user