-
-
Save jpenca/b033122fcb2300c5e9e4 to your computer and use it in GitHub Desktop.
samplechain padding algo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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