Created
October 6, 2017 23:19
-
-
Save sdroege/ee3a449a5a8ee6c3db96ae989098bbc3 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
$ gcc -v | |
gcc version 6.4.0 20170724 (Debian 6.4.0-2) | |
$ gcc -O3 -o test-c test.c | |
$ gcc -O3 -o test-c2 test2.c | |
$ clang --version | |
clang version 3.8.1-24 (tags/RELEASE_381/final) | |
$ clang -O3 -o test-c-clang test.c | |
$ clang -O3 -o test-c2-clang test2.c | |
$ rustc -v | |
rustc 1.20.0 (f3d6973f4 2017-08-27) | |
$ rustc -C opt-level=3 test.rs -o test-rs | |
$ time ./test-rs 100000000 50000000 0.5 0.0 1000000 1024 | |
0 | |
11.87user 0.00system 0:11.87elapsed 100%CPU (0avgtext+0avgdata 2252maxresident)k | |
0inputs+0outputs (0major+141minor)pagefaults 0swaps | |
$ time ./test-c 100000000 50000000 0.5 0.0 1000000 1024 | |
0.000000 | |
19.47user 0.00system 0:19.47elapsed 100%CPU (0avgtext+0avgdata 1428maxresident)k | |
0inputs+0outputs (0major+75minor)pagefaults 0swaps | |
$ time ./test-c2 100000000 50000000 0.5 0.0 1000000 1024 | |
0.000000 | |
13.26user 0.00system 0:13.26elapsed 99%CPU (0avgtext+0avgdata 1476maxresident)k | |
0inputs+0outputs (0major+75minor)pagefaults 0swaps | |
ime ./test-c-clang 100000000 50000000 0.5 0.0 1000000 1024 | |
0.000000 | |
15.85user 0.00system 0:15.85elapsed 100%CPU (0avgtext+0avgdata 1484maxresident)k | |
0inputs+0outputs (0major+76minor)pagefaults 0swaps | |
time ./test-c2-clang 100000000 50000000 0.5 0.0 1000000 1024 | |
0.000000 | |
11.50user 0.00system 0:11.50elapsed 100%CPU (0avgtext+0avgdata 1380maxresident)k | |
0inputs+0outputs (0major+74minor)pagefaults 0swaps |
This file contains hidden or 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
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#define RATE 48000 | |
#define SECOND 1000000000 | |
typedef struct { | |
double *buffer; | |
size_t pos, size; | |
} Buffer; | |
typedef struct { | |
uint64_t max_delay; | |
uint64_t delay; | |
double intensity; | |
double feedback; | |
} Settings; | |
static void | |
process(double *data, unsigned int num_samples, Buffer *buffer, Settings *settings) { | |
size_t i; | |
size_t echo_offset = buffer->size - (settings->delay * RATE / SECOND); | |
double intensity = settings->intensity; | |
double feedback = settings->feedback; | |
double *buffer_data = buffer->buffer; | |
size_t buffer_pos = buffer->pos; | |
size_t buffer_size = buffer->size; | |
for (i = 0; i < num_samples; i++) { | |
size_t echo_index = (echo_offset + buffer_pos) % buffer_size; | |
size_t rbout_index = buffer_pos % buffer_size; | |
double in = data[i]; | |
double echo = buffer_data[echo_index]; | |
double out = in + intensity * echo; | |
data[i] = out; | |
buffer_data[rbout_index] = in + feedback * echo; | |
buffer_pos = (buffer_pos + 1) % buffer_size; | |
} | |
buffer->pos = buffer_pos; | |
} | |
static void | |
parse_commandline_args(char **argv, Settings * settings, size_t *n_buffers, size_t *samples_per_buffer) { | |
settings->max_delay = strtoul(argv[1], NULL, 10); | |
settings->delay = strtoul(argv[2], NULL, 10); | |
settings->intensity = strtod(argv[3], NULL); | |
settings->feedback = strtod(argv[4], NULL); | |
*n_buffers = strtoul(argv[5], NULL, 10); | |
*samples_per_buffer = strtoul(argv[6], NULL, 10); | |
} | |
int | |
main(int argc, char **argv) { | |
Settings settings; | |
Buffer buffer; | |
size_t n_buffers; | |
size_t samples_per_buffer; | |
size_t i; | |
double *data; | |
parse_commandline_args(argv, &settings, &n_buffers, &samples_per_buffer); | |
buffer.pos = 0; | |
buffer.size = settings.max_delay * RATE / SECOND; | |
buffer.buffer = calloc(buffer.size, sizeof(double)); | |
data = calloc(samples_per_buffer, sizeof(double)); | |
for (i = 0; i < n_buffers; i++) { | |
process(data, samples_per_buffer, &buffer, &settings); | |
} | |
printf("%lf\n", data[0]); | |
} |
This file contains hidden or 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
use std::{iter, i32, u64, env}; | |
const RATE: i32 = 48_000; | |
const SECOND: u64 = 1_000_000_000; | |
#[derive(Debug, Clone, Copy)] | |
struct Settings { | |
pub max_delay: u64, | |
pub delay: u64, | |
pub intensity: f64, | |
pub feedback: f64, | |
} | |
struct State { | |
buffer: RingBuffer, | |
} | |
fn process(data: &mut [f64], state: &mut State, settings: &Settings) { | |
let delay_frames = (settings.delay as usize) * (RATE as usize) / (SECOND as usize); | |
for (i, (o, e)) in data.iter_mut().zip(state.buffer.iter(delay_frames)) { | |
let inp = *i; | |
let out = inp + settings.intensity * e; | |
*o = inp + settings.feedback * e; | |
*i = out; | |
} | |
} | |
pub fn main() { | |
let args: Vec<String> = env::args().collect(); | |
let settings = Settings { | |
max_delay: args[1].parse().unwrap(), | |
delay: args[2].parse().unwrap(), | |
intensity: args[3].parse().unwrap(), | |
feedback: args[4].parse().unwrap(), | |
}; | |
let mut state = State { | |
buffer: RingBuffer::new((settings.max_delay as usize) * (RATE as usize) / (SECOND as usize)), | |
}; | |
let n_buffers: usize = args[5].parse().unwrap(); | |
let samples_per_buffer: usize = args[6].parse().unwrap(); | |
let mut buffer: Vec<f64> = Vec::with_capacity(samples_per_buffer); | |
buffer.extend(iter::repeat(0.0).take(samples_per_buffer as usize)); | |
for _ in 0..n_buffers { | |
process(buffer.as_mut_slice(), &mut state, &settings); | |
} | |
println!("{}", buffer[0]); | |
} | |
struct RingBuffer { | |
buffer: Vec<f64>, | |
pos: usize, | |
size: usize, | |
} | |
impl RingBuffer { | |
fn new(size: usize) -> Self { | |
let mut buffer = Vec::with_capacity(size as usize); | |
buffer.extend(iter::repeat(0.0).take(size as usize)); | |
Self { | |
buffer: buffer, | |
pos: 0, | |
size: size, | |
} | |
} | |
fn iter(&mut self, delay: usize) -> RingBufferIter { | |
RingBufferIter::new(self, delay) | |
} | |
} | |
struct RingBufferIter<'a> { | |
buffer: &'a mut RingBuffer, | |
ptr: *mut f64, | |
read_pos: usize, | |
write_pos: usize, | |
} | |
impl<'a> RingBufferIter<'a> { | |
fn new(buffer: &'a mut RingBuffer, delay: usize) -> RingBufferIter<'a> { | |
assert!(buffer.size >= delay); | |
assert_ne!(buffer.size, 0); | |
let ptr = buffer.buffer.as_mut_ptr(); | |
let read_pos = (buffer.size - delay + buffer.pos) % buffer.size; | |
let write_pos = buffer.pos % buffer.size; | |
RingBufferIter { | |
buffer: buffer, | |
ptr: ptr, | |
read_pos: read_pos, | |
write_pos: write_pos, | |
} | |
} | |
} | |
impl<'a> Iterator for RingBufferIter<'a> { | |
type Item = (&'a mut f64, f64); | |
fn next(&mut self) -> Option<Self::Item> { | |
unsafe { | |
let res = (&mut *self.ptr.offset(self.write_pos as isize), *self.ptr.offset(self.read_pos as isize)); | |
self.write_pos = (self.write_pos + 1) % self.buffer.size; | |
self.read_pos = (self.read_pos + 1) % self.buffer.size; | |
Some(res) | |
} | |
} | |
} |
This file contains hidden or 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
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#define RATE 48000 | |
#define SECOND 1000000000 | |
typedef struct { | |
double *buffer; | |
size_t pos, size; | |
} Buffer; | |
typedef struct { | |
uint64_t max_delay; | |
uint64_t delay; | |
double intensity; | |
double feedback; | |
} Settings; | |
static void | |
process(double *data, unsigned int num_samples, Buffer *buffer, Settings *settings) { | |
size_t i; | |
size_t echo_offset = buffer->size - (settings->delay * RATE / SECOND); | |
double intensity = settings->intensity; | |
double feedback = settings->feedback; | |
double *buffer_data = buffer->buffer; | |
size_t buffer_size = buffer->size; | |
size_t write_pos = buffer->pos; | |
size_t read_pos = (echo_offset + write_pos) % buffer_size; | |
for (i = 0; i < num_samples; i++) { | |
double in = data[i]; | |
double echo = buffer_data[read_pos]; | |
double out = in + intensity * echo; | |
data[i] = out; | |
buffer_data[write_pos] = in + feedback * echo; | |
write_pos = (write_pos + 1) % buffer_size; | |
read_pos = (read_pos + 1) % buffer_size; | |
} | |
buffer->pos = write_pos; | |
} | |
static void | |
parse_commandline_args(char **argv, Settings * settings, size_t *n_buffers, size_t *samples_per_buffer) { | |
settings->max_delay = strtoul(argv[1], NULL, 10); | |
settings->delay = strtoul(argv[2], NULL, 10); | |
settings->intensity = strtod(argv[3], NULL); | |
settings->feedback = strtod(argv[4], NULL); | |
*n_buffers = strtoul(argv[5], NULL, 10); | |
*samples_per_buffer = strtoul(argv[6], NULL, 10); | |
} | |
int | |
main(int argc, char **argv) { | |
Settings settings; | |
Buffer buffer; | |
size_t n_buffers; | |
size_t samples_per_buffer; | |
size_t i; | |
double *data; | |
parse_commandline_args(argv, &settings, &n_buffers, &samples_per_buffer); | |
buffer.pos = 0; | |
buffer.size = settings.max_delay * RATE / SECOND; | |
buffer.buffer = calloc(buffer.size, sizeof(double)); | |
data = calloc(samples_per_buffer, sizeof(double)); | |
for (i = 0; i < n_buffers; i++) { | |
process(data, samples_per_buffer, &buffer, &settings); | |
} | |
printf("%lf\n", data[0]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment