ref: f151c6ff228d08e8ca540ac7e44a3cc15f4d5da0
parent: e6d1e3cad1eb9ef8f59afb597f5dddddb5bf86aa
author: David Bryant <[email protected]>
date: Wed Nov 27 11:32:57 EST 2019
- add command-line option to sinusoidally cycle through ratio range - update to version 0.2 (README and main.c)
--- a/README
+++ b/README
@@ -40,6 +40,13 @@
them correctly (by resampling), but it is possible that some applications
will barf on them.
+For version 0.2 a new option was added to cycle through the full possible
+ratio range in a sinusoidal pattern, starting at 1.0, and either going
+up (-c) or down (-cc) first. In this case any specified ratio is ignored
+(except if the -s option is also specified to scale the sampling rate).
+The total period is fixed at 2π seconds, at which point the output will
+again be exactly aligned with the input.
+
To build the demo app:
$ gcc -O2 *.c -o audio-stretch
@@ -46,7 +53,7 @@
The "help" display from the demo app:
- AUDIO-STRETCH Time Domain Harmonic Scaling Demo Version 0.1
+ AUDIO-STRETCH Time Domain Harmonic Scaling Demo Version 0.2
Copyright (c) 2019 David Bryant. All Rights Reserved.
Usage: AUDIO-STRETCH [-options] infile.wav outfile.wav
@@ -54,6 +61,8 @@
Options: -r<n.n> = stretch ratio (0.5 to 2.0, default = 1.0)
-u<n> = upper freq period limit (default = 333 Hz)
-l<n> = lower freq period limit (default = 55 Hz)
+ -c = cycle through all ratios, starting higher
+ -cc = cycle through all ratios, starting lower
-s = scale rate to preserve duration (not pitch)
-f = fast pitch detection (default >= 32 kHz)
-n = normal pitch detection (default < 32 kHz)
@@ -68,6 +77,7 @@
1. The program will handle only mono or stereo files in the WAV format. The
audio must be 16-bit PCM and the acceptable sampling rates are from 8,000
to 48,000 Hz. Any additional RIFF info in the WAV file will be discarded.
+ The command-line program is only for little-endian architectures.
2. For stereo files, the pitch detection is done on a mono conversion of the
audio, but the scaling transformation is done on the independent channels.
--- a/main.c
+++ b/main.c
@@ -14,11 +14,12 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
+#include <math.h>
#include "stretch.h"
static const char *sign_on = "\n"
-" AUDIO-STRETCH Time Domain Harmonic Scaling Demo Version 0.1\n"
+" AUDIO-STRETCH Time Domain Harmonic Scaling Demo Version 0.2\n"
" Copyright (c) 2019 David Bryant. All Rights Reserved.\n\n";
static const char *usage =
@@ -26,6 +27,8 @@
" Options: -r<n.n> = stretch ratio (0.5 to 2.0, default = 1.0)\n"
" -u<n> = upper freq period limit (default = 333 Hz)\n"
" -l<n> = lower freq period limit (default = 55 Hz)\n"
+" -c = cycle through all ratios, starting higher\n"
+" -cc = cycle through all ratios, starting lower\n"
" -s = scale rate to preserve duration (not pitch)\n"
" -f = fast pitch detection (default >= 32 kHz)\n"
" -n = normal pitch detection (default < 32 kHz)\n"
@@ -71,7 +74,7 @@
int main (argc, argv) int argc; char **argv;
{
- int asked_help = 0, overwrite = 0, scale_rate = 0, force_fast = 0, force_normal = 0, fast_mode, scaled_rate;
+ int asked_help = 0, overwrite = 0, scale_rate = 0, force_fast = 0, force_normal = 0, cycle_ratio = 0;
int upper_frequency = 333, lower_frequency = 55, min_period, max_period;
int samples_to_process, insamples = 0, outsamples = 0;
char *infilename = NULL, *outfilename = NULL;
@@ -130,6 +133,10 @@
scale_rate = 1;
break;
+ case 'C': case 'c':
+ cycle_ratio++;
+ break;
+
case 'F': case 'f':
force_fast = 1;
break;
@@ -301,15 +308,18 @@
min_period = WaveHeader.SampleRate / upper_frequency;
max_period = WaveHeader.SampleRate / lower_frequency;
- fast_mode = (force_fast || WaveHeader.SampleRate >= 32000) && !force_normal;
+ int fast_mode = (force_fast || WaveHeader.SampleRate >= 32000) && !force_normal;
if (verbose_mode)
fprintf (stderr, "initializing stretch library with period range = %d to %d, %d channels, %s\n",
min_period, max_period, WaveHeader.NumChannels, fast_mode ? "fast mode" : "normal mode");
- if (!quiet_mode && ratio == 1.0)
+ if (!quiet_mode && ratio == 1.0 && !cycle_ratio)
fprintf (stderr, "warning: a ratio of 1.0 will do nothing but copy the WAV file!\n");
+ if (!quiet_mode && ratio != 1.0 && cycle_ratio && !scale_rate)
+ fprintf (stderr, "warning: specifying ratio with cycling doesn't do anything (unless scaling rate)\n");
+
stretcher = stretch_init (min_period, max_period, WaveHeader.NumChannels, fast_mode);
if (!stretcher) {
@@ -324,11 +334,11 @@
return 1;
}
- scaled_rate = scale_rate ? (int)(WaveHeader.SampleRate * ratio + 0.5) : WaveHeader.SampleRate;
+ int scaled_rate = scale_rate ? (int)(WaveHeader.SampleRate * ratio + 0.5) : WaveHeader.SampleRate;
write_pcm_wav_header (outfile, 0, WaveHeader.NumChannels, 2, scaled_rate);
short *inbuffer = malloc (BUFFER_SAMPLES * WaveHeader.BlockAlign);
- short *outbuffer = malloc ((BUFFER_SAMPLES * 2 + 2048) * WaveHeader.BlockAlign);
+ short *outbuffer = malloc ((BUFFER_SAMPLES * 2 + max_period * 3) * WaveHeader.BlockAlign);
while (1) {
int samples_read = fread (inbuffer, WaveHeader.BlockAlign,
@@ -337,6 +347,9 @@
insamples += samples_read;
samples_to_process -= samples_read;
+
+ if (cycle_ratio)
+ ratio = (sin ((double) outsamples / WaveHeader.SampleRate) * (cycle_ratio & 1 ? 0.75 : -0.75)) + 1.25;
if (samples_read)
samples_generated = stretch_samples (stretcher, inbuffer, samples_read, outbuffer, ratio);