aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2015-12-27 03:50:51 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2015-12-27 03:50:51 +0300
commit5d7ebdd8cc837ff124e132210e3c0e6220be05a8 (patch)
treed8a5e87b125298c2a48f376753f22cd165018ac2
parent7b4f49be99f5ef669c1a268cec5858854b45bd1f (diff)
downloadatracdenc-5d7ebdd8cc837ff124e132210e3c0e6220be05a8.tar.gz
use libsndfile instead of own wav reader
-rw-r--r--README.md10
-rw-r--r--src/CMakeLists.txt9
-rw-r--r--src/cmake/modules/FindLibSndFile.cmake26
-rw-r--r--src/main.cpp18
-rw-r--r--src/wav.cpp82
-rw-r--r--src/wav.h49
6 files changed, 78 insertions, 116 deletions
diff --git a/README.md b/README.md
index 60ef03c..3cc48c9 100644
--- a/README.md
+++ b/README.md
@@ -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();
}
-
-
diff --git a/src/wav.h b/src/wav.h
index fa979c7..991f5dc 100644
--- a/src/wav.h
+++ b/src/wav.h
@@ -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);
}
});
}