audio-effects.test.js 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /* global WebAudioTestAPI */
  2. import 'web-audio-test-api';
  3. WebAudioTestAPI.setState({
  4. 'OfflineAudioContext#startRendering': 'promise'
  5. });
  6. import AudioEffects from '../../../src/lib/audio/audio-effects';
  7. import RobotEffect from '../../../src/lib/audio/effects/robot-effect';
  8. import EchoEffect from '../../../src/lib/audio/effects/echo-effect';
  9. import VolumeEffect from '../../../src/lib/audio/effects/volume-effect';
  10. describe('Audio Effects manager', () => {
  11. const audioContext = new AudioContext();
  12. const audioBuffer = audioContext.createBuffer(1, 400, 44100);
  13. test('changes buffer length and playback rate for faster effect', () => {
  14. const audioEffects = new AudioEffects(audioBuffer, 'faster', 0, 1);
  15. expect(audioEffects.audioContext._.length).toBeLessThan(400);
  16. });
  17. test('changes buffer length and playback rate for slower effect', () => {
  18. const audioEffects = new AudioEffects(audioBuffer, 'slower', 0, 1);
  19. expect(audioEffects.audioContext._.length).toBeGreaterThan(400);
  20. });
  21. test('changes buffer length for echo effect', () => {
  22. const audioEffects = new AudioEffects(audioBuffer, 'echo', 0, 1);
  23. expect(audioEffects.audioContext._.length).toBeGreaterThan(400);
  24. });
  25. test('updates the trim positions after an effect has changed the length of selection', () => {
  26. const slowerEffect = new AudioEffects(audioBuffer, 'slower', 0.25, 0.75);
  27. expect(slowerEffect.adjustedTrimStartSeconds).toEqual(slowerEffect.trimStartSeconds);
  28. expect(slowerEffect.adjustedTrimEndSeconds).toBeGreaterThan(slowerEffect.trimEndSeconds);
  29. const fasterEffect = new AudioEffects(audioBuffer, 'faster', 0.25, 0.75);
  30. expect(fasterEffect.adjustedTrimStartSeconds).toEqual(fasterEffect.trimStartSeconds);
  31. expect(fasterEffect.adjustedTrimEndSeconds).toBeLessThan(fasterEffect.trimEndSeconds);
  32. // Some effects do not change the length of the selection
  33. const fadeEffect = new AudioEffects(audioBuffer, 'fade in', 0.25, 0.75);
  34. expect(fadeEffect.adjustedTrimStartSeconds).toEqual(fadeEffect.trimStartSeconds);
  35. // Should be within one millisecond (flooring can change the duration by one sample)
  36. expect(fadeEffect.adjustedTrimEndSeconds).toBeCloseTo(fadeEffect.trimEndSeconds, 3);
  37. });
  38. test.skip('process starts the offline rendering context and returns a promise', () => {
  39. // @todo haven't been able to get web audio test api to actually run render
  40. });
  41. test('reverse effect strictly reverses the samples', () => {
  42. const fakeSound = [1, 2, 3, 4, 5, 6, 7, 8];
  43. const fakeBuffer = audioContext.createBuffer(1, 8, 44100);
  44. const bufferData = fakeBuffer.getChannelData(0);
  45. fakeSound.forEach((sample, index) => {
  46. bufferData[index] = sample;
  47. });
  48. // Reverse the entire sound
  49. const reverseAll = new AudioEffects(fakeBuffer, 'reverse', 0, 1);
  50. expect(Array.from(reverseAll.buffer.getChannelData(0))).toEqual(fakeSound.reverse());
  51. // Reverse part of the sound
  52. const reverseSelection = new AudioEffects(fakeBuffer, 'reverse', 0.25, 0.75);
  53. const selectionReversed = [1, 2, 6, 5, 4, 3, 7, 8];
  54. expect(Array.from(reverseSelection.buffer.getChannelData(0))).toEqual(selectionReversed);
  55. });
  56. });
  57. describe('Effects', () => {
  58. let audioContext;
  59. beforeEach(() => {
  60. audioContext = new AudioContext();
  61. });
  62. test('all effects provide an input and output that are connected', () => {
  63. const robotEffect = new RobotEffect(audioContext, 0, 1);
  64. expect(robotEffect.input).toBeInstanceOf(AudioNode);
  65. expect(robotEffect.output).toBeInstanceOf(AudioNode);
  66. const echoEffect = new EchoEffect(audioContext, 0, 1);
  67. expect(echoEffect.input).toBeInstanceOf(AudioNode);
  68. expect(echoEffect.output).toBeInstanceOf(AudioNode);
  69. const volumeEffect = new VolumeEffect(audioContext, 0.5, 0, 1);
  70. expect(volumeEffect.input).toBeInstanceOf(AudioNode);
  71. expect(volumeEffect.output).toBeInstanceOf(AudioNode);
  72. });
  73. });