Skip to content

Commit

Permalink
changed the way we're looping over the samples. We're now looking onl…
Browse files Browse the repository at this point in the history
…y once at each input sample. we're not seeking in the input file. This is required for reading from stdin to work. A small drawback is, that we have to collect all output values in a vector before output.
  • Loading branch information
beschulz committed Feb 25, 2015
1 parent 14aebae commit bb14132
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 57 deletions.
31 changes: 10 additions & 21 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,27 +71,16 @@ int main(int argc, char* argv[])
return 2;
}

for(size_t i = 0; i != options.channels.size(); ++i)
{
wav.seek(0, SEEK_SET);

Options::Channel channel = options.channels[i];

ofs << " \"" << channel << "\":";

compute_waveform(
wav,
ofs,
options.samples,
channel,
options.use_db_scale,
options.db_min,
options.db_max,
progress_callback
);

ofs << "," << std::endl;
}
compute_waveform(
wav,
ofs,
options.samples,
options.channels,
options.use_db_scale,
options.db_min,
options.db_max,
progress_callback
);

// increase precission for duration
ofs << std::fixed; //explicitly use fixed notation
Expand Down
99 changes: 64 additions & 35 deletions src/wav2json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,13 @@ void compute_waveform(
const SndfileHandle& wav,
std::ostream& output_stream,
size_t samples,
Options::Channel channel,
Options::Channels channels,
bool use_db_scale,
float db_min,
float db_max,
progress_callback_t progress_callback
)
{
output_stream << "[";

using std::size_t;
using std::cerr;
using std::endl;
Expand All @@ -113,20 +111,34 @@ void compute_waveform(
// temp buffer for samples from audio file
std::vector<sample_type> block(samples_per_pixel);

if (
(channel == Options::MID ||
channel == Options::SIDE ||
channel == Options::RIGHT||
channel == Options::MIN ||
channel == Options::MAX
) &&
wav.channels() == 1
)
// filter out channels, that require more channels than the wav file has
channels.erase(
std::remove_if(channels.begin(), channels.end(), [&wav](Options::Channel channel){
if ((channel == Options::MID ||
channel == Options::SIDE ||
channel == Options::RIGHT||
channel == Options::MIN ||
channel == Options::MAX) &&
wav.channels() == 1
)
{
std::cerr << "Warning: your trying to generate output for channel '" << channel << "', but the input has only one channel. removing requested channel." << std::endl;
return true;
}
return false;
}),
channels.end()
);

if (channels.empty())
{
std::cerr << "Warning: your trying to generate output for channel '" << channel << "', but the input has only one channel. falling back to the left channel." << std::endl;
channel = Options::LEFT;
std::cerr << "Warning: there are no channels left to process, aborting." << endl;
return;
}

// create one vector of floats for each requested channel
std::vector<std::vector<float> > output_values( channels.size() );

// https://github.com/beschulz/wav2json/pull/7
// http://www.mega-nerd.com/libsndfile/api.html#note2
const_cast<SndfileHandle&>(wav).command(SFC_SET_SCALE_FLOAT_INT_READ, 0, SF_TRUE);
Expand All @@ -138,38 +150,55 @@ void compute_waveform(
*/
for (size_t x = 0; x < samples; ++x)
{
// read frames
// read frames
sf_count_t n = const_cast<SndfileHandle&>(wav).readf(&block[0], frames_per_pixel) * wav.channels();
assert(n <= (sf_count_t)block.size());

// find min and max
sample_type max(0);
for (int i=0; i<n; i+=wav.channels()) // only left channel
// for each requested channel
for(size_t channel_idx = 0; channel_idx != channels.size(); ++channel_idx)
{
sample_type sample = compute_sample(block, i, wav.channels(), channel);
sample_type abs_sample = std::abs(sample);
max = std::max( max, abs_sample );
}
// find min and max
sample_type max(0);

Options::Channel channel = channels[channel_idx];
for (int i=0; i<n; i+=wav.channels()) // seek to next frame
{
sample_type sample = compute_sample(block, i, wav.channels(), channel);
sample_type abs_sample = std::abs(sample);
max = std::max( max, abs_sample );
}

float y = use_db_scale?
map2range( float2db(max / (float)sample_scale<sample_type>::value ), db_min, db_max, 0, 1):
map2range( max, 0, sample_scale<sample_type>::value, 0, 1);

// print progress
if ( x%(progress_divisor) == 0 )
{
if ( progress_callback && !progress_callback( 100*x/samples ) )
return;
}

float y = use_db_scale?
map2range( float2db(max / (float)sample_scale<sample_type>::value ), db_min, db_max, 0, 1):
map2range( max, 0, sample_scale<sample_type>::value, 0, 1);
output_values[channel_idx].push_back(y);
}
}

output_stream << y;
if (x != samples-1) //only write out comma, if this is not the last sample
output_stream << ",";
// finally output the collected values
for(size_t channel_idx = 0; channel_idx != channels.size(); ++channel_idx)
{
Options::Channel channel = channels[channel_idx];

// print progress
if ( x%(progress_divisor) == 0 )
output_stream << " \"" << channel << "\": [";
for (size_t i = 0; i != output_values[channel_idx].size(); ++i)
{
if ( progress_callback && !progress_callback( 100*x/samples ) )
return;
output_stream << output_values[channel_idx][i];
if (i != output_values[channel_idx].size()-1)
output_stream << ","; // only output comma, if not the last ellement
}
output_stream << "]," << endl;
}

// call the progress callback
if ( progress_callback && !progress_callback( 100 ) )
return;

output_stream << "]";
}
2 changes: 1 addition & 1 deletion src/wav2json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void compute_waveform(
const SndfileHandle& wav,
std::ostream& output_stream,
size_t samples,
Options::Channel channel,
Options::Channels channels,
bool use_db_scale,
float db_min,
float db_max,
Expand Down

0 comments on commit bb14132

Please sign in to comment.