Skip to content

Commit fb6118d

Browse files
committed
Close #37
1 parent 14bda56 commit fb6118d

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Regression guard for https://github.com/AudioKit/SoundpipeAudioKit/issues/37
2+
// (tenseness=1 reportedly silencing the generator). The bug no longer repros
3+
// in offline render; these tests assert the boundary values still produce audio.
4+
5+
import AudioKit
6+
import AVFoundation
7+
import SoundpipeAudioKit
8+
import XCTest
9+
10+
class VocalTractTenseness1Tests: XCTestCase {
11+
func testTensenessZeroToOneSnap() {
12+
assertAudible(setup: { $0.tenseness = 0.0 }, transition: { $0.tenseness = 1.0 })
13+
}
14+
15+
func testTensenessZeroToOneRamp() {
16+
assertAudible(setup: { $0.tenseness = 0.0 },
17+
transition: { $0.$tenseness.ramp(to: 1.0, duration: 0.1) })
18+
}
19+
20+
func testTensenessStartsAtOne() {
21+
assertAudible(setup: { $0.tenseness = 1.0 }, transition: { _ in })
22+
}
23+
24+
func testTensenessOneToZero() {
25+
assertAudible(setup: { $0.tenseness = 1.0 }, transition: { $0.tenseness = 0.0 })
26+
}
27+
28+
private func assertAudible(setup: (VocalTract) -> Void,
29+
transition: (VocalTract) -> Void,
30+
file: StaticString = #filePath,
31+
line: UInt = #line) {
32+
let engine = AudioEngine()
33+
let vocalTract = VocalTract()
34+
setup(vocalTract)
35+
engine.output = vocalTract
36+
37+
let audio = engine.startTest(totalDuration: 2.0)
38+
vocalTract.start()
39+
audio.append(engine.render(duration: 1.0))
40+
transition(vocalTract)
41+
let after = engine.render(duration: 1.0)
42+
audio.append(after)
43+
engine.stop()
44+
45+
XCTAssertGreaterThan(rms(of: after), 1e-5, "near-silent output", file: file, line: line)
46+
XCTAssertFalse(hasNonFinite(after), "NaN/Inf in output", file: file, line: line)
47+
}
48+
49+
private func rms(of buffer: AVAudioPCMBuffer) -> Float {
50+
guard let data = buffer.floatChannelData else { return 0 }
51+
let frames = Int(buffer.frameLength)
52+
let channels = Int(buffer.format.channelCount)
53+
var sumSq: Double = 0
54+
for ch in 0 ..< channels {
55+
for i in 0 ..< frames {
56+
let s = Double(data[ch][i])
57+
if s.isFinite { sumSq += s * s }
58+
}
59+
}
60+
let n = Double(frames * channels)
61+
return n > 0 ? Float((sumSq / n).squareRoot()) : 0
62+
}
63+
64+
private func hasNonFinite(_ buffer: AVAudioPCMBuffer) -> Bool {
65+
guard let data = buffer.floatChannelData else { return false }
66+
let frames = Int(buffer.frameLength)
67+
for ch in 0 ..< Int(buffer.format.channelCount) {
68+
for i in 0 ..< frames where !data[ch][i].isFinite { return true }
69+
}
70+
return false
71+
}
72+
}

0 commit comments

Comments
 (0)