You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
11KB

  1. // Copyright 2014 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. #include <cassert>
  27. #include <cmath>
  28. #include <cstdlib>
  29. #include <cstring>
  30. #include <vector>
  31. #include <xmmintrin.h>
  32. #include "stmlib/test/wav_writer.h"
  33. #include "stmlib/utils/random.h"
  34. #include "warps/dsp/modulator.h"
  35. #include "warps/dsp/sample_rate_converter.h"
  36. #include "warps/resources.h"
  37. using namespace warps;
  38. using namespace std;
  39. using namespace stmlib;
  40. const size_t kSampleRate = 96000;
  41. const size_t kBlockSize = 96;
  42. template<typename T>
  43. void TestSRCUp(const char* name) {
  44. size_t ratio = 6;
  45. WavWriter wav_writer(1, kSampleRate * ratio, 10);
  46. wav_writer.Open(name);
  47. T src_up;
  48. src_up.Init();
  49. float phase = 0.0f;
  50. while (!wav_writer.done()) {
  51. float samples_in[kBlockSize];
  52. float samples_out[kBlockSize * ratio];
  53. float instantenous_frequency = fmod(
  54. 4.0f * wav_writer.progress(),
  55. 0.5f);
  56. for (size_t i = 0; i < kBlockSize; ++i) {
  57. samples_in[i] = sinf(phase * 2 * M_PI);
  58. phase += instantenous_frequency;
  59. if (phase >= 1.0f) {
  60. phase -= 1.0f;
  61. }
  62. }
  63. src_up.Process(samples_in, samples_out, kBlockSize);
  64. wav_writer.Write(samples_out, kBlockSize * ratio, 16067.0f);
  65. }
  66. }
  67. void TestSRC96To576To96() {
  68. size_t ratio = 6;
  69. WavWriter wav_writer(1, kSampleRate, 10);
  70. wav_writer.Open("warps_src_96_576_96.wav");
  71. SampleRateConverter<SRC_UP, 6, 48> src_up;
  72. SampleRateConverter<SRC_DOWN, 6, 48> src_down;
  73. src_up.Init();
  74. src_down.Init();
  75. float phase = 0.0f;
  76. while (!wav_writer.done()) {
  77. float samples_in[kBlockSize];
  78. float samples_out[kBlockSize * ratio];
  79. float instantenous_frequency = fmod(
  80. 2.0f * wav_writer.progress(),
  81. 0.5f);
  82. for (size_t i = 0; i < kBlockSize; ++i) {
  83. samples_in[i] = sinf(phase * 2 * M_PI);
  84. phase += instantenous_frequency;
  85. if (phase >= 1.0f) {
  86. phase -= 1.0f;
  87. }
  88. }
  89. src_up.Process(samples_in, samples_out, kBlockSize);
  90. src_down.Process(samples_out, samples_in, kBlockSize * ratio);
  91. wav_writer.Write(samples_in, kBlockSize, 32200.0f);
  92. }
  93. }
  94. void TestModulator() {
  95. FILE* fp_in = fopen("audio_samples/modulation_96k.wav", "rb");
  96. WavWriter wav_writer(2, kSampleRate, 15);
  97. wav_writer.Open("warps_modulator.wav");
  98. fseek(fp_in, 48, SEEK_SET);
  99. Modulator modulator;
  100. modulator.Init(kSampleRate);
  101. Parameters* p = modulator.mutable_parameters();
  102. float phi = 0.0f;
  103. float filtered_noise = 0.0f;
  104. while (!wav_writer.done()) {
  105. float triangle = wav_writer.triangle();
  106. float square = 0.5f * SoftClip(32.0f * (triangle - 0.5f)) + 0.5f;
  107. float noise = (Random::GetFloat() - 0.5f) / 128.0f;
  108. filtered_noise += (noise - filtered_noise) * 0.1f;
  109. p->carrier_shape = 1;
  110. p->channel_drive[0] = 0.625f;
  111. p->channel_drive[1] = 0.0f;
  112. p->modulation_algorithm = 0.125f + 0.0f * square + 1.0f * filtered_noise;
  113. p->modulation_parameter = 0.0f + 1.0f * triangle;
  114. p->note = 48.0f + phi;
  115. ShortFrame input[kBlockSize];
  116. ShortFrame output[kBlockSize];
  117. if (fread(
  118. input,
  119. sizeof(ShortFrame),
  120. kBlockSize,
  121. fp_in) != kBlockSize) {
  122. break;
  123. }
  124. for (size_t i = 0; i < kBlockSize; ++i) {
  125. input[i].r = input[i].l;
  126. input[i].l = 0;
  127. }
  128. modulator.Process(input, output, kBlockSize);
  129. wav_writer.WriteFrames((short*)(output), kBlockSize);
  130. }
  131. fclose(fp_in);
  132. }
  133. void TestEasterEgg() {
  134. FILE* fp_in = fopen("audio_samples/ericderr96.wav", "rb");
  135. WavWriter wav_writer(2, kSampleRate, 15);
  136. wav_writer.Open("warps_easter_egg.wav");
  137. fseek(fp_in, 48, SEEK_SET);
  138. Modulator modulator;
  139. modulator.Init(kSampleRate);
  140. modulator.set_feature_mode(FEATURE_MODE_CHEBYSCHEV);
  141. Parameters* p = modulator.mutable_parameters();
  142. float phi = 0.0f;
  143. float filtered_noise = 0.0f;
  144. while (!wav_writer.done()) {
  145. uint16_t tri = (wav_writer.remaining_frames() / 8);
  146. tri = tri > 32767 ? 65535 - tri : tri;
  147. float triangle = 0.5f * SoftClip(8.0f * (tri / 32768.0f - 0.5f)) + 0.5f;
  148. float square = 0.5f * SoftClip(32.0f * (tri / 32768.0f - 0.5f)) + 0.5f;
  149. float noise = (Random::GetFloat() - 0.5f) / 128.0f;
  150. filtered_noise += (noise - filtered_noise) * 0.1f;
  151. p->raw_algorithm_pot = 1.0f + 0.0f * triangle + 0.0f * square;
  152. p->raw_algorithm_cv = 0.0f;
  153. p->raw_algorithm = 0.0f;// + 0.0f * triangle;// + 0.1f * filtered_noise;
  154. p->modulation_algorithm = 0.3f;// + 1.0f * triangle;
  155. p->carrier_shape = 0;
  156. p->channel_drive[0] = 0.5f;
  157. p->channel_drive[1] = 0.0f;
  158. p->raw_level[0] = 0.6f;
  159. p->raw_level[1] = 1.0f;
  160. p->modulation_parameter = 1.0f;// + 0.05f * filtered_noise;
  161. p->note = 48.0f + phi;
  162. ShortFrame input[kBlockSize];
  163. ShortFrame output[kBlockSize];
  164. if (fread(
  165. input,
  166. sizeof(ShortFrame),
  167. kBlockSize,
  168. fp_in) != kBlockSize) {
  169. break;
  170. }
  171. for (size_t i = 0; i < kBlockSize; ++i) {
  172. input[i].r = input[i].r;
  173. input[i].l = input[i].l;
  174. }
  175. modulator.Process(input, output, kBlockSize);
  176. wav_writer.WriteFrames((short*)(output), kBlockSize);
  177. }
  178. fclose(fp_in);
  179. }
  180. void TestOscillators() {
  181. WavWriter wav_writer(2, kSampleRate, 15);
  182. wav_writer.Open("warps_oscillator.wav");
  183. Modulator modulator;
  184. modulator.Init(kSampleRate);
  185. Parameters* p = modulator.mutable_parameters();
  186. p->carrier_shape = 1;
  187. p->channel_drive[0] = 0.0f;
  188. p->channel_drive[1] = 0.0f;
  189. p->modulation_algorithm = 0.0f;
  190. p->modulation_parameter = 0.0f;
  191. ShortFrame input[kBlockSize];
  192. ShortFrame zero;
  193. zero.l = zero.r = 0.0f;
  194. fill(&input[0], &input[kBlockSize], zero);
  195. while (!wav_writer.done()) {
  196. float triangle = wav_writer.triangle();
  197. p->note = 20 + triangle * 0;
  198. ShortFrame output[kBlockSize];
  199. modulator.Process(input, output, kBlockSize);
  200. wav_writer.WriteFrames((short*)(output), kBlockSize);
  201. }
  202. }
  203. void TestFilterBankReconstruction() {
  204. FilterBank fb;
  205. fb.Init(96000.0);
  206. size_t num_blocks = 1000;
  207. const size_t block_size = 96;
  208. FILE* fp_out = fopen("warps_filterbank_ir_float32.bin", "wb");
  209. float in[block_size];
  210. float out[block_size];
  211. for (size_t i = 0; i < num_blocks; ++i) {
  212. fill(&in[0], &in[block_size], 0.0f);
  213. if (i == 0) {
  214. in[0] = 1.0f;
  215. }
  216. fb.Analyze(in, block_size);
  217. for (int32_t j = 0; j < kNumBands; ++j) {
  218. if (false) {
  219. float* samples = fb.band(j).samples;
  220. size_t size = block_size / fb.band(j).decimation_factor;
  221. fill(&samples[0], &samples[size], 0.0f);
  222. }
  223. }
  224. fb.Synthesize(out, block_size);
  225. fwrite(out, sizeof(float), block_size, fp_out);
  226. }
  227. fclose(fp_out);
  228. // The impulse response and frequency responses can be seen with the following
  229. // python program:
  230. //
  231. // import numpy
  232. // import pylab
  233. //
  234. // x = numpy.fromfile('warps_filterbank_ir_float32.bin', dtype=numpy.float32)
  235. // pylab.subplot(211)
  236. // pylab.plot(x[:500])
  237. // pylab.subplot(212)
  238. // xf = numpy.fft.rfft(x)
  239. // N = len(xf)
  240. // f = numpy.arange(0.0, N) / N * 48000
  241. // pylab.semilogx(f, 20 * numpy.log10(numpy.abs(xf + 1e-8)))
  242. // pylab.show()
  243. }
  244. void TestSineTransition() {
  245. WavWriter wav_writer(2, kSampleRate, 15);
  246. wav_writer.Open("warps_sine_transition.wav");
  247. Modulator modulator;
  248. modulator.Init(kSampleRate);
  249. Parameters* p = modulator.mutable_parameters();
  250. while (!wav_writer.done()) {
  251. float triangle = wav_writer.triangle();
  252. p->carrier_shape = 1;
  253. p->channel_drive[0] = 0.0;
  254. p->channel_drive[1] = 0.0f;
  255. p->modulation_algorithm = 0.0f + 0.125f * triangle;
  256. p->modulation_parameter = 0.0f;
  257. p->note = 36.0f;
  258. ShortFrame input[kBlockSize];
  259. ShortFrame output[kBlockSize];
  260. for (size_t i = 0; i < kBlockSize; ++i) {
  261. input[i].r = 0;
  262. input[i].l = 0;
  263. }
  264. modulator.Process(input, output, kBlockSize);
  265. wav_writer.WriteFrames((short*)output, kBlockSize);
  266. }
  267. }
  268. void TestGain() {
  269. WavWriter wav_writer(2, kSampleRate, 10);
  270. wav_writer.Open("warps_gain.wav");
  271. Modulator modulator;
  272. modulator.Init(kSampleRate);
  273. Parameters* p = modulator.mutable_parameters();
  274. float phase = 0.0f;
  275. while (!wav_writer.done()) {
  276. float triangle = wav_writer.triangle();
  277. p->carrier_shape = 0;
  278. p->channel_drive[0] = triangle * 1.0f;
  279. p->channel_drive[1] = 0.0f;
  280. p->modulation_algorithm = 0.0f + 0.125f * 0.0f;
  281. p->modulation_parameter = 0.0f;
  282. p->note = 36.0f;
  283. ShortFrame input[kBlockSize];
  284. ShortFrame output[kBlockSize];
  285. for (size_t i = 0; i < kBlockSize; ++i) {
  286. input[i].l = 20480.0f * sinf(phase * 2 * M_PI);
  287. input[i].r = 20480.0f * sinf(phase * 2 * M_PI);
  288. phase += 220.0f / kSampleRate;
  289. if (phase >= 1.0f) {
  290. phase -= 1.0f;
  291. }
  292. }
  293. modulator.Process(input, output, kBlockSize);
  294. wav_writer.WriteFrames((short*)output, kBlockSize);
  295. }
  296. }
  297. void TestQuadratureOscillator() {
  298. WavWriter wav_writer(2, kSampleRate, 10);
  299. wav_writer.Open("warps_quadrature.wav");
  300. QuadratureOscillator q;
  301. q.Init(kSampleRate);
  302. while (!wav_writer.done()) {
  303. float triangle = wav_writer.triangle();
  304. float x[2];
  305. q.Render(triangle, 100.8f, &x[0], &x[1], 1);
  306. wav_writer.Write(x, 2, 32767.0f);
  307. }
  308. }
  309. int main(void) {
  310. _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
  311. //TestSRCUp<SampleRateConverter<SRC_UP, 6, 48> >("warps_src_up_fir_48.wav");
  312. //TestSRC96To576To96();
  313. // TestModulator();
  314. TestEasterEgg();
  315. //TestOscillators();
  316. //TestFilterBankReconstruction();
  317. //TestSineTransition();
  318. //TestGain();
  319. //TestQuadratureOscillator();
  320. }