Skip to content

Instantly share code, notes, and snippets.

@jpenca

jpenca/main.cpp Secret

Last active March 22, 2016 12:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpenca/b033122fcb2300c5e9e4 to your computer and use it in GitHub Desktop.
Save jpenca/b033122fcb2300c5e9e4 to your computer and use it in GitHub Desktop.
samplechain padding algo
//
// main.cpp
// Slice
//
// Created by Jakob Penca on 20/03/16.
// Copyright © 2016 Jakob Penca. All rights reserved.
//
#include <iostream>
#include <cmath>
#include <chrono>
using namespace std;
using namespace std::chrono;
// we want to align the inputs to a 120 grid, but it should work with other positive numbers.
#define grid 120
static size_t num_inputs = 11;
// these test inputs are meant to be PCM sample frame counts:
static size_t inputs[] =
{34004,11800,38356,35744,4834,13106,14846,15282,34004,43146,5704};
//{1,100000};
static size_t paddings[] =
{0,0,0,0,0,0,0,0,0,0,0,0};
static size_t sum = 0;
static size_t iter_cnt = 0;
void crunch();
void print_results();
int main()
{
cout << "chain crunch for " << num_inputs << " slices\n------" << endl;
high_resolution_clock::time_point t1 = high_resolution_clock::now();
crunch();
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = duration_cast<microseconds>( t2 - t1 ).count();
double milliSeconds = duration / (double)1000;
print_results();
cout << "the operation took: " << milliSeconds << " ms to finish.\n------" << endl;
return 0;
}
/* calculate total sum of sample frames including padding */
void update_sum()
{
sum = 0;
for(int i = 0; i < num_inputs; i++)
{
sum += inputs[i] + paddings[i];
}
}
/*
* this algorithm keeps adding 1 sample frame at a time to an element until
* the ratios between the element fit neatly into the 120 division.
*/
void crunch()
{
update_sum();
bool good;
do
{
iter_cnt++;
good = true;
int selectedElement = 0;
double minCeilDist = 1;
double minRatio = 1.0 / grid;
// loop over all inputs
for(int i = 0; i < num_inputs; i++)
{
// ratio of current element to the sum of all elements including padding
double doubRatio = (inputs[i] + paddings[i]) / (double)sum;
// handle a case where an element is smaller than the minimum (sum/grid)
if(doubRatio < minRatio)
{
selectedElement = i;
good = false;
break;
}
// find the element closest to become a full integer step in the grid
double doubUnits = doubRatio * grid;
double ceilUnits = ceil(doubUnits);
if(ceilUnits != doubUnits)
{
good = false;
double d = fabs(ceilUnits - doubUnits);
if(d < minCeilDist)
{
minCeilDist = d;
selectedElement = i;
}
}
}
// add one frame of padding to the found element
if(!good)
{
paddings[selectedElement]++;
sum++;
}
}
while (!good);
}
void print_results()
{
double curr = 0;
for(int i = 0; i < num_inputs; i++)
{
double doub_ratio = (inputs[i] + paddings[i]) / (double)sum;
double doub_units = doub_ratio * grid;
printf("slice %2d in: %6lu out: %6lu pad: %4lu sta: %3d end: %3d\n",
i,
inputs[i],
inputs[i] + paddings[i],
paddings[i],
(int)curr,
(int)(curr + doub_units));
curr += doub_units;
}
printf("------\n");
size_t orig_sum = 0;
size_t total_padding = 0;
for(int i = 0; i < num_inputs; i++)
{
orig_sum += inputs[i];
total_padding += paddings[i];
}
double pad_percent = (double)total_padding / orig_sum * 100;
printf(" in sum: %lu\n"
"out sum: %lu\n"
"padding: %lu (%.2f %%)\n", orig_sum, sum, total_padding, pad_percent);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment