diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2015-12-27 03:50:51 +0300 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2015-12-27 03:50:51 +0300 |
commit | 5d7ebdd8cc837ff124e132210e3c0e6220be05a8 (patch) | |
tree | d8a5e87b125298c2a48f376753f22cd165018ac2 | |
parent | 7b4f49be99f5ef669c1a268cec5858854b45bd1f (diff) | |
download | atracdenc-5d7ebdd8cc837ff124e132210e3c0e6220be05a8.tar.gz |
use libsndfile instead of own wav reader
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | src/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/cmake/modules/FindLibSndFile.cmake | 26 | ||||
-rw-r--r-- | src/main.cpp | 18 | ||||
-rw-r--r-- | src/wav.cpp | 82 | ||||
-rw-r--r-- | src/wav.h | 49 |
6 files changed, 78 insertions, 116 deletions
@@ -3,8 +3,14 @@ Implementation of ATRAC1 encoder Building: You need C++11 compiler. -Currently we do not use cmake, have no install target in Makefile. To build it just type `make` in `src` dir. -Likely atracdenc executable file will be builded )) +cmake > 2.8 +libsndfiles + +`cd src` +`mkdir build` +`cd build` +`cmake ../` +`make` Usage: You can use --help option to get help diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd7daec..5299e95 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,10 +5,17 @@ set(CMAKE_CXX_STANDARD 11) project(atracdenc) +set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules") +INCLUDE(FindLibSndFile) + +find_package(libsndfile REQUIRED) + +include_directories(${LIBSNDFILE_INCLUDE_DIR}) + set(SOURCE_LIB mdct/vorbis_impl/mdct.c) set(SOURCE_EXE main.cpp wav.cpp aea.cpp transient_detector.cpp atracdenc.cpp bitstream/bitstream.cpp atrac/atrac1.cpp atrac/atrac1_dequantiser.cpp atrac/atrac1_scale.cpp atrac/atrac1_bitalloc.cpp) add_library(mdct_impl STATIC ${SOURCE_LIB}) add_executable(atracdenc ${SOURCE_EXE}) -target_link_libraries(atracdenc mdct_impl) +target_link_libraries(atracdenc mdct_impl ${SNDFILE_LIBRARIES}) diff --git a/src/cmake/modules/FindLibSndFile.cmake b/src/cmake/modules/FindLibSndFile.cmake new file mode 100644 index 0000000..12a6880 --- /dev/null +++ b/src/cmake/modules/FindLibSndFile.cmake @@ -0,0 +1,26 @@ + +if (LIBSNDFILE_INCLUDE_DIR AND SNDFILE_LIBRARY) + # Already in cache, be silent + set(LIBSNDFILE_FIND_QUIETLY TRUE) +endif (LIBSNDFILE_INCLUDE_DIR AND SNDFILE_LIBRARY) + +find_path(LIBSNDFILE_INCLUDE_DIR sndfile.h + PATHS /usr/include /opt/local/include/ +) + +find_library(SNDFILE_LIBRARY + NAMES sndfile + PATHS /usr/lib /usr/local/lib /opt/local/lib +) + +set(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY}) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(LIBSNDFILE + DEFAULT_MSG + LIBSNDFILE_INCLUDE_DIR + SNDFILE_LIBRARIES +) + +mark_as_advanced(LIBSNDFILE_INCLUDE_DIR SNDFILE_LIBRARY) diff --git a/src/main.cpp b/src/main.cpp index 013c5c5..1706a19 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -140,18 +140,18 @@ int main(int argc, char* const* argv) { uint64_t totalSamples = 0; if (mode == E_ENCODE) { wavIO = TWavPtr(new TWav(inFile)); - const TWavHeader& wavHeader = wavIO->GetWavHeader(); - const int numChannels = wavHeader.NumOfChan; - totalSamples = wavHeader.ChunkSize; - aeaIO = TAeaPtr(new TAea(outFile, "test", numChannels, totalSamples / 2 / 512)); + const int numChannels = wavIO->GetChannelNum(); + totalSamples = wavIO->GetTotalSamples(); + //TODO: recheck it + aeaIO = TAeaPtr(new TAea(outFile, "test", numChannels, numChannels * totalSamples / 512)); pcmEngine = new TPCMEngine<double>(4096, numChannels, TPCMEngine<double>::TReaderPtr(wavIO->GetPCMReader<double>())); - cout << "Input file: " << inFile << "Channels: " << numChannels << "SampleRate: " << wavHeader.SamplesPerSec << "TotalSamples: " << totalSamples << endl; + cout << "Input file: " << inFile << "\n Channels: " << numChannels << "\n SampleRate: " << wavIO->GetSampleRate() << "\n TotalSamples: " << totalSamples << endl; } else if (mode == E_DECODE) { aeaIO = TAeaPtr(new TAea(inFile)); - totalSamples = 4 * aeaIO->GetLengthInSamples(); + totalSamples = aeaIO->GetLengthInSamples(); uint32_t length = aeaIO->GetLengthInSamples(); cout << "Name: " << aeaIO->GetName() << "\n Channels: " << aeaIO->GetChannelNum() << "\n Length: " << length << endl; - wavIO = TWavPtr(new TWav(outFile, TWav::CreateHeader(aeaIO->GetChannelNum(), length))); + wavIO = TWavPtr(new TWav(outFile, aeaIO->GetChannelNum(), 44100)); pcmEngine = new TPCMEngine<double>(4096, aeaIO->GetChannelNum(), TPCMEngine<double>::TWriterPtr(wavIO->GetPCMWriter<double>())); } else { cout << "Processing mode was not specified" << endl; @@ -163,9 +163,9 @@ int main(int argc, char* const* argv) { atrac1Processor.GetEncodeLambda(TAtrac1EncodeSettings(bfuIdxConst, fastBfuNumSearch, windowMode, winMask)); uint64_t processed = 0; try { - while (totalSamples/4 > (processed = pcmEngine->ApplyProcess(512, atracLambda))) + while (totalSamples > (processed = pcmEngine->ApplyProcess(512, atracLambda))) { - printProgress(processed*100/(totalSamples/4)); + printProgress(processed*100/totalSamples); } cout << "\nDone" << endl; } diff --git a/src/wav.cpp b/src/wav.cpp index fdc4366..755fcd7 100644 --- a/src/wav.cpp +++ b/src/wav.cpp @@ -9,78 +9,26 @@ #include "pcmengin.h" -using namespace std; - -TWavHeader TWav::CreateHeader(int channels, uint32_t length) { - TWavHeader header; - uint32_t dataLen = length * 2 * channels; - const char dataString[] = "data"; - header.RIFF[0] = 0x52; - header.RIFF[1] = 0x49; - header.RIFF[2] = 0x46; - header.RIFF[3] = 0x46; - header.ChunkSize = dataLen + sizeof(TWavHeader) - 8;; - header.WAVE[0] = 0x57; - header.WAVE[1] = 0x41; - header.WAVE[2] = 0x56; - header.WAVE[3] = 0x45; - header.fmt[0] = 0x66; - header.fmt[1] = 0x6d; - header.fmt[2] = 0x74; - header.fmt[3] = 0x20; - header.Subchunk1Size = 16; - header.AudioFormat = 1; - header.NumOfChan = channels; - header.SamplesPerSec = 44100; //samplerate; - header.bytesPerSec = 44100 * ((16 * channels) / 8); - header.blockAlign = 2 * channels; - header.bitsPerSample = 16; - strncpy(&header.Subchunk2ID[0], dataString, sizeof(dataString)); - header.Subchunk2Size = dataLen; - - return header; -} - -TWav::TMeta TWav::ReadWavHeader(const string& filename) { - FILE* fd = fopen(filename.c_str(), "rb"); - if (!fd) - throw TWavIOError("Can't open file to read", errno); - TWavHeader headerBuf; - if (fread(&headerBuf, sizeof(TWavHeader), 1, fd) != 1) { - const int errnum = errno; - fclose(fd); - throw TWavIOError("Can't read WAV header", errnum); - } - return {fd, headerBuf}; +TWav::TWav(const std::string& filename) + : File(SndfileHandle(filename)) { + //disable scaling short -> [-1.0, 1.0] + File.command(SFC_SET_NORM_DOUBLE /*| SFC_SET_NORM_FLOAT*/, nullptr, SF_FALSE); } -TWav::TMeta TWav::CreateFileAndHeader(const string& filename, const TWavHeader& header, bool overwrite) { - (void)overwrite; - - FILE* fd = fopen(filename.c_str(), "wb"); - if (!fd) - throw TWavIOError("Can't open file to write", errno); - if (fwrite(&header, sizeof(TWavHeader), 1, fd) != 1) { - const int errnum = errno; - fclose(fd); - throw TWavIOError("Can't write WAV header", errnum); - } - return {fd, header}; +TWav::TWav(const std::string& filename, int channels, int sampleRate) + : File(SndfileHandle(filename, SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_PCM_16, channels, sampleRate)) { + //disable scaling short -> [-1.0, 1.0] + File.command(SFC_SET_NORM_DOUBLE /*| SFC_SET_NORM_FLOAT*/, nullptr, SF_FALSE); } - -TWav::TWav(const string& filename) - : Meta(ReadWavHeader(filename)) { +TWav::~TWav() { } -TWav::TWav(const string& filename, const TWavHeader& header, bool overwrite) - : Meta(CreateFileAndHeader(filename, header, overwrite)) { +uint64_t TWav::GetTotalSamples() const { + return File.frames(); } -TWav::~TWav() { - fclose(Meta.WavFile); +uint32_t TWav::GetChannelNum() const { + return File.channels(); } - -const TWavHeader& TWav::GetWavHeader() const { - return Meta.Header; +uint32_t TWav::GetSampleRate() const { + return File.samplerate(); } - - @@ -3,23 +3,9 @@ #include <memory> #include <string> -#include "pcmengin.h" +#include <sndfile.hh> -typedef struct WAV_HEADER { - char RIFF[4]; // RIFF Header Magic header - unsigned int ChunkSize; // RIFF Chunk Size - char WAVE[4]; // WAVE Header - char fmt[4]; // FMT header - unsigned int Subchunk1Size; // Size of the fmt chunk - unsigned short AudioFormat; // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM - unsigned short NumOfChan; // Number of channels 1=Mono 2=Sterio - unsigned int SamplesPerSec; // Sampling Frequency in Hz - unsigned int bytesPerSec; // bytes per second - unsigned short blockAlign; // 2=16-bit mono, 4=16-bit stereo - unsigned short bitsPerSample; // Number of bits per sample - char Subchunk2ID[4]; // "data" string - unsigned int Subchunk2Size; // Sampled data length -} __attribute__((packed)) TWavHeader; +#include "pcmengin.h" class TFileAlreadyExists : public std::exception { @@ -32,7 +18,9 @@ public: TWavIOError(const char* str, int err) : ErrNum(err) , Text(str) - {} + { + (void)ErrNum; + } virtual const char* what() const throw() { return Text; } @@ -65,24 +53,18 @@ public: }; class TWav { - struct TMeta { - FILE* WavFile; - const TWavHeader Header; - } Meta; - static TWav::TMeta ReadWavHeader(const std::string& filename); - static TWav::TMeta CreateFileAndHeader(const std::string& filename, const TWavHeader& header, bool overwrite); + mutable SndfileHandle File; public: - static TWavHeader CreateHeader(int channels, uint32_t length); enum Mode { E_READ, E_WRITE }; TWav(const std::string& filename); // reading - TWav(const std::string& filename, const TWavHeader& header, bool overwrite = false); //writing + TWav(const std::string& filename, int channels, int sampleRate); //writing ~TWav(); uint32_t GetChannelNum() const; uint32_t GetSampleRate() const; - const TWavHeader& GetWavHeader() const; + uint64_t GetTotalSamples() const; template<class T> IPCMReader<T>* GetPCMReader() const; @@ -95,15 +77,11 @@ typedef std::unique_ptr<TWav> TWavPtr; template<class T> IPCMReader<T>* TWav::GetPCMReader() const { return new TWavPcmReader<T>([this](std::vector<std::vector<T>>& data, const uint32_t size) { - if (data[0].size() != Meta.Header.NumOfChan) + if (data[0].size() != File.channels()) throw TWrongReadBuffer(); uint32_t dataRead = 0; for (uint32_t i = 0; i < size; i++) { - for (uint32_t c = 0; c < Meta.Header.NumOfChan; c++) { - short buf; - dataRead += fread(&buf, Meta.Header.bitsPerSample/8, 1, Meta.WavFile); - data[i][c] = (T)buf; - } + dataRead += File.readf(&data[i][0], 1); } }); } @@ -111,14 +89,11 @@ IPCMReader<T>* TWav::GetPCMReader() const { template<class T> IPCMWriter<T>* TWav::GetPCMWriter() { return new TWavPcmWriter<T>([this](const std::vector<std::vector<T>>& data, const uint32_t size) { - if (data[0].size() != Meta.Header.NumOfChan) + if (data[0].size() != File.channels()) throw TWrongReadBuffer(); uint32_t dataWrite = 0; for (uint32_t i = 0; i < size; i++) { - for (uint32_t c = 0; c < Meta.Header.NumOfChan; c++) { - short buf = (short)data[i][c]; - dataWrite += fwrite(&buf, Meta.Header.bitsPerSample/8, 1, Meta.WavFile); - } + dataWrite += File.writef(&data[i][0], 1); } }); } |