summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-constant-source.html
blob: 0bea5c91f8538e6b0e9d587af1b5c8e4b018ab62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<!doctype html>
<html>
  <head>
    <title>Test k-rate AudioParam of ConstantSourceNode</title>
    <script src="/resources/testharness.js"></script>
    <script src="/resources/testharnessreport.js"></script>
    <script src="/webaudio/resources/audit-util.js"></script>
    <script src="/webaudio/resources/audit.js"></script>
    <script src="automation-rate-testing.js"></script>
  </head>

  <body>
    <script>
      let audit = Audit.createTaskRunner();

      audit.define('ConstantSource k-rate offset', (task, should) => {
        // Arbitrary sample rate and duration.
        let sampleRate = 8000;

        // Only new a few render quanta to verify things are working.
        let testDuration = 4 * 128 / sampleRate;

        let context = new OfflineAudioContext({
          numberOfChannels: 3,
          sampleRate: sampleRate,
          length: testDuration * sampleRate
        });

        doTest(context, should, {
          sourceNodeName: 'none',
          verifyPieceWiseConstant: true,
          nodeName: 'ConstantSourceNode',
          prefix: 'k-rate offset',
          rateSettings: [{name: 'offset', value: 'k-rate'}],
          automations: [{
            name: 'offset',
            methods: [
              {name: 'setValueAtTime', options: [0, 0]}, {
                name: 'linearRampToValueAtTime',
                options: [10, testDuration]
              }
            ]
          }]
        }).then(() => task.done());
      });

      // Parameters for the For the following tests.

      // Must be power of two to eliminate round-off
      const sampleRate8k = 8192;

      // Arbitrary duration that doesn't need to be too long to verify k-rate
      // automations.  Probably should be at least a few render quanta.
      const testDuration = 8 * RENDER_QUANTUM_FRAMES / sampleRate8k;

      // Basic test that k-rate ConstantSourceNode.offset is k-rate.  This is
      // the basis for all of the following tests, so make sure it's right.
      audit.define(
          {
            label: 'ConstantSourceNode.offset k-rate automation',
            description:
                'Explicitly test ConstantSourceNode.offset k-rate automation is k-rate'
          },
          (task, should) => {
            let context = new OfflineAudioContext({
              numberOfChannels: 2,
              sampleRate: sampleRate8k,
              length: testDuration * sampleRate8k
            });
            let merger = new ChannelMergerNode(
                context, {numberOfInputs: context.destination.channelCount});
            merger.connect(context.destination);

            // k-rate ConstantSource.offset using a linear ramp starting at 0
            // and incrementing by 1 for each frame.
            let src = new ConstantSourceNode(context, {offset: 0});
            src.offset.automationRate = 'k-rate';

            src.offset.setValueAtTime(0, 0);
            src.offset.linearRampToValueAtTime(context.length, testDuration);

            src.connect(merger, 0, 0);

            src.start();

            // a-rate ConstantSource using the same ramp as above.
            let refSrc = new ConstantSourceNode(context, {offset: 0});

            refSrc.offset.setValueAtTime(0, 0);
            refSrc.offset.linearRampToValueAtTime(context.length, testDuration);

            refSrc.connect(merger, 0, 1);

            refSrc.start();

            context.startRendering()
                .then(buffer => {
                  let actual = buffer.getChannelData(0);
                  let expected = buffer.getChannelData(1);

                  for (let k = 0; k < actual.length;
                       k += RENDER_QUANTUM_FRAMES) {
                    // Verify that the k-rate output is constant over the render
                    // and that it matches the value of the a-rate value at the
                    // beginning of the render.
                    should(
                        actual.slice(k, k + RENDER_QUANTUM_FRAMES),
                        `k-rate ConstantSource.offset:  output[${k}:${
                            k + RENDER_QUANTUM_FRAMES}]`)
                        .beConstantValueOf(expected[k]);
                  }
                })
                .then(() => task.done());
          });

      // This test verifies that a k-rate input to the ConstantSourceNode.offset
      // works just as if we set the AudioParam to be k-rate.  This is the basis
      // of the following tests, so make sure it works.
      audit.define(
          {
            label: 'ConstantSource.offset',
            description: 'Verify k-rate automation matches k-rate input'
          },
          (task, should) => {
            let context = new OfflineAudioContext({
              numberOfChannels: 2,
              sampleRate: sampleRate8k,
              length: testDuration * sampleRate8k
            });

            let merger = new ChannelMergerNode(
                context, {numberOfInputs: context.destination.channelCount});
            merger.connect(context.destination);

            let tstSrc = new ConstantSourceNode(context);
            let tstMod = new ConstantSourceNode(context);
            tstSrc.offset.automationRate = 'k-rate';
            tstMod.offset.linearRampToValueAtTime(context.length, testDuration);

            tstMod.connect(tstSrc.offset)
            tstSrc.connect(merger, 0, 0);

            let refSrc = new ConstantSourceNode(context);
            let refMod = new ConstantSourceNode(context);
            refMod.offset.linearRampToValueAtTime(context.length, testDuration);
            refMod.offset.automationRate = 'k-rate';

            refMod.connect(refSrc.offset);
            refSrc.connect(merger, 0, 1);

            tstSrc.start();
            tstMod.start();
            refSrc.start();
            refMod.start();

            context.startRendering()
                .then(buffer => {
                  let actual = buffer.getChannelData(0);
                  let expected = buffer.getChannelData(1);

                  for (let k = 0; k < context.length;
                       k += RENDER_QUANTUM_FRAMES) {
                    should(
                        actual.slice(k, k + RENDER_QUANTUM_FRAMES),
                        `ConstantSource.offset k-rate input: output[${k}:${
                            k + RENDER_QUANTUM_FRAMES}]`)
                        .beConstantValueOf(expected[k]);
                  }
                })
                .then(() => task.done());
          });

      audit.run();
    </script>
  </body>
</html>