removed unwanted bar now with waveforms, major updates and enhancements
This commit is contained in:
@@ -3053,7 +3053,7 @@ extension KJamsCloneTests {
|
||||
for song in dj.songs { XCTAssertNotNil(try WaveformCache.load(audio:URL(fileURLWithPath:song.audio),directory:dj.waveformDirectory)) }
|
||||
}
|
||||
|
||||
@MainActor func testAddingLoopToPlayingTrackDoesNotRestartAudioNode() async throws {
|
||||
@MainActor func testAddingLoopReplacesFileCommandsOnceAndKeepsRepeating() async throws {
|
||||
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
||||
defer { try? FileManager.default.removeItem(at:root) }
|
||||
let fixture = try XCTUnwrap(Bundle(for:Self.self).resourceURL?.appendingPathComponent("Fixtures/Demo.wav"))
|
||||
@@ -3066,11 +3066,11 @@ extension KJamsCloneTests {
|
||||
player.defineLoop(start:start,end:start+0.3)
|
||||
for _ in 0..<100 where !player.nativeLoopActive { try await Task.sleep(nanoseconds:10_000_000) }
|
||||
XCTAssertTrue(player.nativeLoopActive);XCTAssertTrue(player.audioPlaybackStarted)
|
||||
XCTAssertEqual(player.audioScheduleRestartCount,restarts,"Adding a live loop must not stop the audio node")
|
||||
XCTAssertEqual(player.audioScheduleRestartCount,restarts+1,"A live file command must be replaced once with the prepared loop")
|
||||
try await Task.sleep(nanoseconds:400_000_000)
|
||||
XCTAssertGreaterThanOrEqual(player.displayTime,start);XCTAssertLessThan(player.displayTime,start+0.301)
|
||||
player.loopEnabled = false
|
||||
XCTAssertEqual(player.audioScheduleRestartCount,restarts,"Cancelling the loop must also leave the audio node running")
|
||||
XCTAssertEqual(player.audioScheduleRestartCount,restarts+1,"Repeating and cancelling must not replace the node commands again")
|
||||
XCTAssertTrue(player.audioPlaybackStarted)
|
||||
}
|
||||
|
||||
@@ -3099,4 +3099,48 @@ extension KJamsCloneTests {
|
||||
XCTAssertTrue(finished);XCTAssertFalse(player.playing)
|
||||
}
|
||||
|
||||
@MainActor func testLiveLoopRepeatsActualAudioRatherThanOnlyWrappingDisplay() async throws {
|
||||
let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
||||
defer { try? FileManager.default.removeItem(at:root) }
|
||||
try FileManager.default.createDirectory(at:root,withIntermediateDirectories:true)
|
||||
let format = try XCTUnwrap(AVAudioFormat(standardFormatWithSampleRate:44100,channels:2))
|
||||
let buffer = try XCTUnwrap(AVAudioPCMBuffer(pcmFormat:format,frameCapacity:132300));buffer.frameLength = 132300
|
||||
let data = try XCTUnwrap(buffer.floatChannelData)
|
||||
for i in 0..<132300 {
|
||||
let amplitude: Float = i < 30870 ? 0.1 : 0.7
|
||||
let value = amplitude*Float(sin(Double(i)*2 * .pi*440/44100))
|
||||
data[0][i] = value;data[1][i] = value
|
||||
}
|
||||
let url = root.appendingPathComponent("LoopSignal.wav")
|
||||
do { let file = try AVAudioFile(forWriting:url,settings:format.settings);try file.write(from:buffer) }
|
||||
let player = Player(waveformCacheDirectory:root.appendingPathComponent("Cache"),persistsMix:false)
|
||||
defer { player.stop() }
|
||||
player.autoFade = false;player.volume = 0.8
|
||||
try player.load(Song(id:1,title:"Loop signal",audio:url.path,cdg:nil,rating:0,plays:0))
|
||||
for _ in 0..<100 where player.displayTime < 0.1 { try await Task.sleep(nanoseconds:10_000_000) }
|
||||
player.defineLoop(start:0.2,end:0.5)
|
||||
for _ in 0..<100 where !player.nativeLoopActive { try await Task.sleep(nanoseconds:10_000_000) }
|
||||
try await Task.sleep(nanoseconds:1_000_000_000)
|
||||
for _ in 0..<10 {
|
||||
XCTAssertGreaterThan(player.scrubOutputLevel,0.02,"Loop audio must remain audible")
|
||||
XCTAssertLessThan(player.scrubOutputLevel,0.2,"The quiet loop must repeat; the loud audio after it must never render")
|
||||
try await Task.sleep(nanoseconds:30_000_000)
|
||||
}
|
||||
let handoffs = player.audioScheduleRestartCount
|
||||
player.defineLoop(start:0.2,end:1.1)
|
||||
var extendedPeak: Float = 0
|
||||
for _ in 0..<50 {
|
||||
try await Task.sleep(nanoseconds:30_000_000)
|
||||
extendedPeak = max(extendedPeak,player.scrubOutputLevel)
|
||||
}
|
||||
XCTAssertGreaterThan(extendedPeak,0.4,"Extending the loop must render its newly included loud section")
|
||||
player.defineLoop(start:0.2,end:0.5)
|
||||
try await Task.sleep(nanoseconds:1_200_000_000)
|
||||
XCTAssertLessThan(player.scrubOutputLevel,0.2,"Shortening must return to the quiet loop audio")
|
||||
player.loopEnabled = false
|
||||
try await Task.sleep(nanoseconds:800_000_000)
|
||||
XCTAssertGreaterThan(player.scrubOutputLevel,0.4,"Loop Off must resume the actual file beyond the loop")
|
||||
XCTAssertEqual(player.audioScheduleRestartCount,handoffs,"Resizing and cancellation must keep the node running")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user