Skip to content

Commit

Permalink
Allow reading and writting 24bits files
Browse files Browse the repository at this point in the history
  • Loading branch information
gvne committed Oct 31, 2017
1 parent 1603954 commit 321595a
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/wave/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include "wave/headers.h"

#define INT24_MAX 8388607

namespace wave {

namespace internal {
Expand Down Expand Up @@ -216,6 +218,19 @@ Error File::Read(uint64_t frame_number, void (*decrypt)(char*, size_t),
decrypt(reinterpret_cast<char*>(&value), sizeof(value) / sizeof(char));
(*output)[sample_idx] =
static_cast<float>(value) / std::numeric_limits<int16_t>::max();
} else if (impl_->header.fmt.bits_per_sample == 24) {
// 24bits int doesn't exist in c++. We create a 3 * 8bits struct to simulate
unsigned char value[3];
impl_->istream.read(reinterpret_cast<char*>(&value), sizeof(value));
decrypt(reinterpret_cast<char*>(&value), sizeof(value) / sizeof(char));
int integer_value;
// check if value is negative
if ( value[2] & 0x80 ) {
integer_value = (0xff << 24) | (value[2] << 16) | (value[1] << 8) | (value[0] << 0);
} else {
integer_value = (value[2] << 16) | (value[1] << 8) | (value[0] << 0);
}
(*output)[sample_idx] = static_cast<float>(integer_value) / INT24_MAX;
} else if (impl_->header.fmt.bits_per_sample == 32) {
// 32bits
int32_t value;
Expand Down Expand Up @@ -257,6 +272,16 @@ Error File::Write(const std::vector<float>& data,
static_cast<int16_t>(sample * std::numeric_limits<int16_t>::max());
encrypt(reinterpret_cast<char*>(&value), sizeof(value) / sizeof(char));
impl_->ostream.write(reinterpret_cast<char*>(&value), sizeof(value));
} else if (bits_per_sample == 24) {
// 24bits int doesn't exist in c++. We create a 3 * 8bits struct to simulate
int v = sample * INT24_MAX;
int8_t value[3];
value[0] = reinterpret_cast<char*>(&v)[0];
value[1] = reinterpret_cast<char*>(&v)[1];
value[2] = reinterpret_cast<char*>(&v)[2];

encrypt(reinterpret_cast<char*>(&value), sizeof(value) / sizeof(char));
impl_->ostream.write(reinterpret_cast<char*>(&value), sizeof(value));
} else if (bits_per_sample == 32) {
// 32bits
int32_t value =
Expand Down
33 changes: 33 additions & 0 deletions src/wave/file_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,39 @@ TEST(Wave, ChunkWrite) {
ASSERT_EQ(content, re_read_content);
}

TEST(Wave, Write24bits) {
using namespace wave;

// tested above
File read_file;
read_file.Open(gResourcePath + "/Untitled3.wav", OpenMode::kIn);
std::vector<float> content;
read_file.Read(&content);

{
File write_file;
write_file.Open(gResourcePath + "/output.wav", OpenMode::kOut);
write_file.set_sample_rate(read_file.sample_rate());
write_file.set_bits_per_sample(24);
write_file.set_channel_number(read_file.channel_number());
write_file.Write(content);
}

// re read
File re_read_file;
re_read_file.Open(gResourcePath + "/output.wav", OpenMode::kIn);
std::vector<float> re_read_content;
re_read_file.Read(&re_read_content);

ASSERT_EQ(read_file.channel_number(), re_read_file.channel_number());
ASSERT_EQ(read_file.sample_rate(), re_read_file.sample_rate());
ASSERT_EQ(read_file.channel_number(), re_read_file.channel_number());
ASSERT_EQ(re_read_file.bits_per_sample(), 24);
for (int i = 0; i < read_file.frame_number(); i++) {
ASSERT_LT(fabs(content[i] - re_read_content[i]), pow(10, -6));
}
}

#if __cplusplus > 199711L
TEST(Wave, ReadModern) {
using namespace wave;
Expand Down

0 comments on commit 321595a

Please sign in to comment.