From 3ff1973d7f12dd02a80d9f14e0e0923512226bbf Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sat, 18 Jul 2026 13:21:23 +0200 Subject: [PATCH] =?UTF-8?q?feat(pyrowave):=20Apple=20Metal=204:4:4=20+=20H?= =?UTF-8?q?DR=20decode,=20EDR=20present=20=E2=80=94=20self-configured=20in?= =?UTF-8?q?-band?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phases 4+5 of design/pyrowave-444-hdr.md. The Metal decoder needs NO new ABI: every frame's sequence header carries chroma (444) and, since the Phase-3 stamps, the PQ/BT.2020 bits — so the decoder self-configures per session. Decoder: WaveletLayout grows the 4:4:4 block space (chroma runs the full pyramid like luma — no level-0 skip, no early half-res emit; the Metal kernels were already chroma-agnostic, only the dispatch structure changes); the parser accepts chroma_resolution=444, reads the PQ transfer bit, and lifts the even-dims rule for 444; the plane ring allocates full-res chroma and r16Unorm for PQ streams; CSC rows switch to depth-10 MSB-packed. Presenter: planar HDR passthrough reuses pf_frag_planar on an rgba16Float drawable (itur_2100_PQ + EDR metadata interpret the samples — same split as pf_frag/pf_frag_hdr), plus a new pf_frag_planar_tm PQ->SDR tone-map (shared pqToSdr tail refactored out of pf_frag_hdr_tv) for tvOS-without-headroom AND macOS WINDOWED sessions, whose IOSurface present path (the DCP-panic mitigation) is BGRA8-only. SessionModel stops stripping the HDR/10-bit/444 caps on the PyroWave opt-in. New golden: au-dense444 + upstream's own 4:4:4 reference planes (regenerated via the extended pyrowave_dump_golden); Metal decode matches at 64-67 dB (420 fixtures re-verify 77-88 dB). Full Apple suite 157 tests green on a real M-series GPU. Docs updated: the 8-bit-SDR-only wording is gone, the Windows host is no longer 'on the roadmap', bpp scaling documented. Co-Authored-By: Claude Fable 5 --- .../Session/SessionModel.swift | 9 +- .../Video/MetalVideoPresenter.swift | 99 +++++++++++++++--- .../Video/MetalWaveletDecoder.swift | 74 +++++++++---- .../PyroWaveDecoderTests.swift | 15 ++- .../PyroWaveFixtures/au-dense444.bin | Bin 0 -> 65452 bytes .../PyroWaveFixtures/ref-dense444-cb.bin | 1 + .../PyroWaveFixtures/ref-dense444-cr.bin | 1 + .../PyroWaveFixtures/ref-dense444-y.bin | 1 + docs-site/content/docs/pyrowave.md | 24 +++-- 9 files changed, 167 insertions(+), 57 deletions(-) create mode 100644 clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/au-dense444.bin create mode 100644 clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-cb.bin create mode 100644 clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-cr.bin create mode 100644 clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-y.bin diff --git a/clients/apple/Sources/PunktfunkClient/Session/SessionModel.swift b/clients/apple/Sources/PunktfunkClient/Session/SessionModel.swift index 12db3065..4e998fcf 100644 --- a/clients/apple/Sources/PunktfunkClient/Session/SessionModel.swift +++ b/clients/apple/Sources/PunktfunkClient/Session/SessionModel.swift @@ -264,14 +264,11 @@ final class SessionModel: ObservableObject { // PyroWave (wired LAN) is a pure opt-in: picking it in the codec setting both // advertises the bit and prefers it — the host never auto-selects it, and the // picker only offers it when the Metal decode probe passed (simdgroup floor ≈ A13; - // every M-series Mac and the ATV 4K gen 3 pass). The codec is 8-bit 4:2:0 SDR - // BT.709 by contract, so the opt-in also drops the HDR/10-bit/4:4:4 caps for this - // session — HDR sessions stay HEVC/AV1 (plan §4.7). + // every M-series Mac and the ATV 4K gen 3 pass). The decoder self-configures from + // the per-frame sequence header (4:2:0/4:4:4, SDR/PQ — design/pyrowave-444-hdr.md), + // so the session keeps the user's HDR/10-bit/4:4:4 caps exactly like HEVC/AV1. if preferredCodec == PunktfunkConnection.codecPyroWave, MetalWaveletDecoder.supported { videoCodecs |= PunktfunkConnection.codecPyroWave - videoCaps &= ~(PunktfunkConnection.videoCap10Bit - | PunktfunkConnection.videoCapHDR - | PunktfunkConnection.videoCap444) } let result = Result { try PunktfunkConnection( host: host.address, port: host.port, diff --git a/clients/apple/Sources/PunktfunkKit/Video/MetalVideoPresenter.swift b/clients/apple/Sources/PunktfunkKit/Video/MetalVideoPresenter.swift index 8612743c..45683735 100644 --- a/clients/apple/Sources/PunktfunkKit/Video/MetalVideoPresenter.swift +++ b/clients/apple/Sources/PunktfunkKit/Video/MetalVideoPresenter.swift @@ -196,13 +196,11 @@ fragment float4 pf_frag_hdr(VOut in [[stage_in]], // display-referred SDR. (When the display IS in an HDR mode — requested per session via // AVDisplayManager, see StreamViewIOS — tvOS presents pf_frag_hdr's PQ passthrough instead: // in a genuine HDR10 output, PQ passthrough is the correct emission and the TV tone-maps.) -fragment float4 pf_frag_hdr_tv(VOut in [[stage_in]], - texture2d lumaTex [[texture(0)]], - texture2d chromaTex [[texture(1)]], - constant CscUniform& csc [[buffer(0)]]) { - // Y′CbCr → full-range PQ R′G′B′ via the per-frame rows (as pf_frag_hdr). - float3 pq = sampleRgb(lumaTex, chromaTex, in.uv, csc); - // ST 2084 EOTF: PQ code value → linear light, 1.0 = 10,000 nits. +// The shared PQ→display-referred-SDR tail (see pf_frag_hdr_tv's rationale above): ST 2084 +// EOTF → 203-nit-anchored scene light → BT.2020→709 primaries → extended-Reinhard rolloff → +// BT.709 OETF. Used by the tvOS biplanar tone-map and the planar (PyroWave) tone-map — the +// latter also on macOS windowed sessions, whose IOSurface present path is BGRA8-only. +static inline float3 pqToSdr(float3 pq) { const float m1 = 2610.0/16384.0; const float m2 = 78.84375; const float c1 = 3424.0/4096.0; @@ -210,20 +208,49 @@ fragment float4 pf_frag_hdr_tv(VOut in [[stage_in]], const float c3 = 18.6875; float3 p = pow(pq, 1.0/m2); float3 lin = pow(max(p - c1, 0.0) / (c2 - c3 * p), 1.0/m1); - // Scene-referred with diffuse white at 1.0 (the same 203-nit anchor the EDR path uses). float3 t = lin * (10000.0/203.0); - // BT.2020 → BT.709 primaries while still linear; negatives are out-of-gamut, floor them. float3 t709 = float3( dot(t, float3( 1.6605, -0.5876, -0.0728)), dot(t, float3(-0.1246, 1.1329, -0.0083)), dot(t, float3(-0.0182, -0.1006, 1.1187))); t709 = max(t709, 0.0); - // Extended Reinhard: 1.0 stays put, the 1000-nit knee lands at display white, above rolls off. const float w = 1000.0/203.0; float3 mapped = saturate(t709 * (1.0 + t709 / (w * w)) / (1.0 + t709)); - // BT.709 OETF — the same encoding the SDR stream arrives in, so both paths present alike. float3 e = select(1.099 * pow(mapped, 0.45) - 0.099, 4.5 * mapped, mapped < 0.018); - return float4(e, 1.0); + return e; +} + +fragment float4 pf_frag_hdr_tv(VOut in [[stage_in]], + texture2d lumaTex [[texture(0)]], + texture2d chromaTex [[texture(1)]], + constant CscUniform& csc [[buffer(0)]]) { + // Y′CbCr → full-range PQ R′G′B′ via the per-frame rows (as pf_frag_hdr), then the tail. + return float4(pqToSdr(sampleRgb(lumaTex, chromaTex, in.uv, csc)), 1.0); +} + +// PyroWave planar HDR tone-map: three separate R16 planes (P010-style studio codes; the rows +// fold in depth-10 MSB packing) → PQ R′G′B′ → the shared SDR tail. Used when a PQ pyrowave +// stream must land on an 8-bit surface: tvOS without HDR headroom, and macOS WINDOWED sessions +// (the IOSurface present path — the DCP-panic mitigation — is BGRA8). The passthrough planar +// HDR pipeline reuses pf_frag_planar itself on an rgba16Float drawable (identical math — the +// layer's itur_2100_PQ colour space + EDR metadata do the interpretation). +fragment float4 pf_frag_planar_tm(VOut in [[stage_in]], + texture2d lumaTex [[texture(0)]], + texture2d cbTex [[texture(1)]], + texture2d crTex [[texture(2)]], + constant CscUniform& csc [[buffer(0)]]) { + constexpr sampler s(filter::linear, address::clamp_to_edge); +#ifdef PF_BILINEAR_LUMA + float lumaY = lumaTex.sample(s, in.uv).r; +#else + float lumaY = catmullRomLuma(lumaTex, s, in.uv); +#endif + float2 cuv = chromaUV(lumaTex, cbTex, in.uv); + float3 yuv = float3(lumaY, cbTex.sample(s, cuv).r, crTex.sample(s, cuv).r); + float3 pq = saturate(float3(dot(csc.r0.xyz, yuv) + csc.r0.w, + dot(csc.r1.xyz, yuv) + csc.r1.w, + dot(csc.r2.xyz, yuv) + csc.r2.w)); + return float4(pqToSdr(pq), 1.0); } """ @@ -287,6 +314,11 @@ public final class MetalVideoPresenter { private let pipelineHDRToneMap: MTLRenderPipelineState? /// PyroWave's 3-plane SDR path (pf_frag_planar → bgra8) — see `renderPlanar`. private let pipelinePlanar: MTLRenderPipelineState + /// PyroWave planar HDR passthrough (pf_frag_planar → rgba16Float; the layer's PQ colour + /// space + EDR interpret the samples) and the planar PQ→SDR tone-map (pf_frag_planar_tm → + /// bgra8; tvOS without headroom + macOS windowed IOSurface presents). + private let pipelinePlanarHDR: MTLRenderPipelineState + private let pipelinePlanarToneMap: MTLRenderPipelineState private var textureCache: CVMetalTextureCache? /// The PyroWave Metal decoder records on the presenter's device + queue: one device means @@ -337,6 +369,8 @@ public final class MetalVideoPresenter { let pipelineHDR: MTLRenderPipelineState let pipelineHDRToneMap: MTLRenderPipelineState? let pipelinePlanar: MTLRenderPipelineState + let pipelinePlanarHDR: MTLRenderPipelineState + let pipelinePlanarToneMap: MTLRenderPipelineState do { // DEBUG A/B lever: PUNKTFUNK_BILINEAR_LUMA=1 compiles the shader with Catmull-Rom OFF // (plain bilinear luma) by prepending a #define ahead of the source. Default (unset) is @@ -374,8 +408,18 @@ public final class MetalVideoPresenter { let planar = MTLRenderPipelineDescriptor() planar.vertexFunction = vtx planar.fragmentFunction = library.makeFunction(name: "pf_frag_planar") - planar.colorAttachments[0].pixelFormat = .bgra8Unorm // PyroWave is 8-bit SDR + planar.colorAttachments[0].pixelFormat = .bgra8Unorm pipelinePlanar = try device.makeRenderPipelineState(descriptor: planar) + let planarHdr = MTLRenderPipelineDescriptor() + planarHdr.vertexFunction = vtx + planarHdr.fragmentFunction = library.makeFunction(name: "pf_frag_planar") + planarHdr.colorAttachments[0].pixelFormat = .rgba16Float // PQ passthrough + pipelinePlanarHDR = try device.makeRenderPipelineState(descriptor: planarHdr) + let planarTm = MTLRenderPipelineDescriptor() + planarTm.vertexFunction = vtx + planarTm.fragmentFunction = library.makeFunction(name: "pf_frag_planar_tm") + planarTm.colorAttachments[0].pixelFormat = .bgra8Unorm + pipelinePlanarToneMap = try device.makeRenderPipelineState(descriptor: planarTm) } catch { return nil } @@ -416,6 +460,7 @@ public final class MetalVideoPresenter { return MetalVideoPresenter( device: device, queue: queue, pipelineSDR: pipelineSDR, pipelineHDR: pipelineHDR, pipelineHDRToneMap: pipelineHDRToneMap, pipelinePlanar: pipelinePlanar, + pipelinePlanarHDR: pipelinePlanarHDR, pipelinePlanarToneMap: pipelinePlanarToneMap, textureCache: textureCache, layer: layer) } @@ -423,6 +468,8 @@ public final class MetalVideoPresenter { device: MTLDevice, queue: MTLCommandQueue, pipelineSDR: MTLRenderPipelineState, pipelineHDR: MTLRenderPipelineState, pipelineHDRToneMap: MTLRenderPipelineState?, pipelinePlanar: MTLRenderPipelineState, + pipelinePlanarHDR: MTLRenderPipelineState, + pipelinePlanarToneMap: MTLRenderPipelineState, textureCache: CVMetalTextureCache, layer: CAMetalLayer ) { self.device = device @@ -431,6 +478,8 @@ public final class MetalVideoPresenter { self.pipelineHDR = pipelineHDR self.pipelineHDRToneMap = pipelineHDRToneMap self.pipelinePlanar = pipelinePlanar + self.pipelinePlanarHDR = pipelinePlanarHDR + self.pipelinePlanarToneMap = pipelinePlanarToneMap self.textureCache = textureCache self.layer = layer } @@ -652,7 +701,13 @@ public final class MetalVideoPresenter { let surfaceMode = surfacePresentsStaged #endif stagingLock.unlock() - configure(hdr: false) + // A PQ (HDR) pyrowave stream drives the same layer/EDR machinery as the biplanar path; + // macOS WINDOWED sessions stay on the SDR layer (the IOSurface path tone-maps in-shader). + #if os(macOS) + configure(hdr: planes.pq && !surfaceMode) + #else + configure(hdr: planes.pq) + #endif var csc = planes.csc #if os(macOS) if surfaceMode != surfacePresentsActive { @@ -672,9 +727,21 @@ public final class MetalVideoPresenter { planes, targetFromLayout: targetFromLayout, csc: &csc, onPresented: onPresented) } #endif + // PQ passthrough needs the HDR drawable; a PQ frame while the drawable is (still) + // 8-bit — tvOS without display headroom, or a not-yet-flipped layer — tone-maps + // in-shader instead (the pipeline must match the drawable's pixel format). + #if os(tvOS) + let planarPassthrough = hdrActive && hdrPassthroughActive + #else + let planarPassthrough = hdrActive + #endif + let planarPipeline: MTLRenderPipelineState = + planes.pq + ? (planarPassthrough ? pipelinePlanarHDR : pipelinePlanarToneMap) + : pipelinePlanar return encodePresent( decodedSize: CGSize(width: planes.width, height: planes.height), - targetFromLayout: targetFromLayout, pipeline: pipelinePlanar, + targetFromLayout: targetFromLayout, pipeline: planarPipeline, presentAtMediaTime: presentAtMediaTime, onPresented: onPresented, // The ring textures stay valid by ring depth; retaining them here also pins the // slot's set until the sample completes (mirrors the biplanar keep-alive). @@ -716,7 +783,7 @@ public final class MetalVideoPresenter { guard let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: pass) else { return false } - encoder.setRenderPipelineState(pipelinePlanar) + encoder.setRenderPipelineState(planes.pq ? pipelinePlanarToneMap : pipelinePlanar) encoder.setFragmentTexture(planes.y, index: 0) encoder.setFragmentTexture(planes.cb, index: 1) encoder.setFragmentTexture(planes.cr, index: 2) diff --git a/clients/apple/Sources/PunktfunkKit/Video/MetalWaveletDecoder.swift b/clients/apple/Sources/PunktfunkKit/Video/MetalWaveletDecoder.swift index a39d6b58..3765fca6 100644 --- a/clients/apple/Sources/PunktfunkKit/Video/MetalWaveletDecoder.swift +++ b/clients/apple/Sources/PunktfunkKit/Video/MetalWaveletDecoder.swift @@ -47,6 +47,9 @@ struct WaveletLayout { let width: Int let height: Int + /// Full-res chroma (4:4:4): chroma components get the full band set including level 0, + /// exactly like luma — upstream `init_block_meta` with `Chroma444`. + let chroma444: Bool let alignedWidth: Int let alignedHeight: Int /// blockMeta[component][level][band] = (blockOffset32x32, blockStride32x32); -1 offset = @@ -59,9 +62,10 @@ struct WaveletLayout { func levelWidth(_ level: Int) -> Int { (alignedWidth / 2) >> level } func levelHeight(_ level: Int) -> Int { (alignedHeight / 2) >> level } - init(width: Int, height: Int) { + init(width: Int, height: Int, chroma444: Bool) { self.width = width self.height = height + self.chroma444 = chroma444 let align = { (v: Int) in max((v + Self.alignment - 1) & ~(Self.alignment - 1), Self.minimumImageSize) } @@ -78,7 +82,7 @@ struct WaveletLayout { let ah = alignedHeight for level in stride(from: Self.decompositionLevels - 1, through: 0, by: -1) { for component in 0..<3 { - if level == 0 && component != 0 { continue } // 4:2:0: no top-level chroma + if level == 0 && component != 0 && !chroma444 { continue } // 4:2:0: no top-level chroma for band in (level == Self.decompositionLevels - 1 ? 0 : 1)..<4 { let levelW = (aw / 2) >> level let levelH = (ah / 2) >> level @@ -108,6 +112,9 @@ struct ParsedWaveletFrame { var decodedBlocks: Int /// VUI bits from the sequence header (BitstreamSequenceHeader). var bt2020: Bool + /// PQ transfer ⇒ HDR session: 16-bit studio-code planes + EDR present (the host stamps + /// this bit iff the session negotiated 10-bit — the depth is coupled to the transfer). + var pq: Bool var fullRange: Bool /// The frame's Y′CbCr→RGB signal for the presenter's planar CSC. PyroWave today is always @@ -203,6 +210,7 @@ enum WaveletBitstream { var totalBlocks = 0 var decodedBlocks = 0 var bt2020 = false + var pq = false var fullRange = false var sawSOF = false @@ -220,22 +228,28 @@ enum WaveletBitstream { // siting[31]. let code = (word1 >> 24) & 0x3 guard code == 0 else { return false } // only START_OF_FRAME is defined - let chromaRes = (word1 >> 26) & 1 - guard chromaRes == 0 else { return false } // host contract: 4:2:0 + let chroma444 = (word1 >> 26) & 1 != 0 let w = Int(word0 & 0x3fff) + 1 let h = Int((word0 >> 14) & 0x3fff) + 1 - guard w >= 2, h >= 2, w % 2 == 0, h % 2 == 0 else { return false } + guard w >= 2, h >= 2, chroma444 || (w % 2 == 0 && h % 2 == 0) else { + return false + } if sawSOF { // One frame, one geometry — a second SOF must agree. - guard layout?.width == w, layout?.height == h else { return false } + guard layout?.width == w, layout?.height == h, + layout?.chroma444 == chroma444 + else { return false } } else { sawSOF = true - let l = WaveletLayout(width: w, height: h) + let l = WaveletLayout(width: w, height: h, chroma444: chroma444) layout = l offsets = [UInt32](repeating: .max, count: l.blockCount32) payload.reserveCapacity(64 * 1024 / 4) totalBlocks = Int(word1 & 0xff_ffff) bt2020 = (word1 >> 29) & 1 != 0 + // transfer_function bit: PQ ⇒ an HDR session (16-bit studio-code + // planes by the negotiated coupling — design/pyrowave-444-hdr.md). + pq = (word1 >> 28) & 1 != 0 fullRange = (word1 >> 30) & 1 == 0 // YCBCR_RANGE_FULL = 0 } pos += 8 @@ -280,7 +294,7 @@ enum WaveletBitstream { return ParsedWaveletFrame( layout: layout, offsets: offsets, payload: payload, totalBlocks: totalBlocks, decodedBlocks: decodedBlocks, - bt2020: bt2020, fullRange: fullRange) + bt2020: bt2020, pq: pq, fullRange: fullRange) } } } @@ -293,6 +307,8 @@ public struct WaveletPlanes: @unchecked Sendable { public let cb: MTLTexture public let cr: MTLTexture public let csc: CscUniform + /// PQ (HDR) stream: the presenter picks the HDR/tone-map planar pipeline + EDR config. + public let pq: Bool public var width: Int { y.width } public var height: Int { y.height } } @@ -351,6 +367,8 @@ public final class MetalWaveletDecoder { private var slots: [Slot] = [] private var nextSlot = 0 + /// The ring's plane format facts (from the last SOF): PQ ⇒ 16-bit UNORM planes. + private var hdr16 = false /// The current geometry (from the last SOF that built the resources) — the pump reports /// decoded-size changes to the resize overlay from this. PUMP THREAD. @@ -409,8 +427,9 @@ public final class MetalWaveletDecoder { au: au, chunkAligned: chunkAligned, windowSize: windowSize) else { return false } - if layout?.width != frame.layout.width || layout?.height != frame.layout.height { - guard rebuild(layout: frame.layout) else { return false } + if layout?.width != frame.layout.width || layout?.height != frame.layout.height + || layout?.chroma444 != frame.layout.chroma444 || hdr16 != frame.pq { + guard rebuild(layout: frame.layout, hdr16: frame.pq) else { return false } } guard let layout, !slots.isEmpty else { return false } @@ -450,7 +469,7 @@ public final class MetalWaveletDecoder { dequant.setBuffer(slot.payload, offset: 0, index: 1) for level in 0.. Bool { + private func rebuild(layout newLayout: WaveletLayout, hdr16 newHdr16: Bool) -> Bool { waveletLog.info( - "pyrowave: building decoder \(newLayout.width)x\(newLayout.height) (aligned \(newLayout.alignedWidth)x\(newLayout.alignedHeight), \(newLayout.blockCount32) blocks)") + "pyrowave: building decoder \(newLayout.width)x\(newLayout.height) (aligned \(newLayout.alignedWidth)x\(newLayout.alignedHeight), \(newLayout.blockCount32) blocks, \(newLayout.chroma444 ? "4:4:4" : "4:2:0", privacy: .public)\(newHdr16 ? " HDR16" : "", privacy: .public))") var coeff: [[MTLTexture]] = [] var lls: [[MTLTexture]] = [] for component in 0..<3 { @@ -560,19 +586,22 @@ public final class MetalWaveletDecoder { var newSlots: [Slot] = [] for i in 0.. MTLTexture? in let desc = MTLTextureDescriptor.texture2DDescriptor( - pixelFormat: .r8Unorm, width: w, height: h, mipmapped: false) + pixelFormat: planeFormat, width: w, height: h, mipmapped: false) desc.usage = [.shaderRead, .shaderWrite] desc.storageMode = .private let t = self.device.makeTexture(descriptor: desc) t?.label = name return t } + let cw = newLayout.chroma444 ? newLayout.width : newLayout.width / 2 + let ch = newLayout.chroma444 ? newLayout.height : newLayout.height / 2 guard let y = plane(newLayout.width, newLayout.height, "pyrowave Y[\(i)]"), - let cb = plane(newLayout.width / 2, newLayout.height / 2, "pyrowave Cb[\(i)]"), - let cr = plane(newLayout.width / 2, newLayout.height / 2, "pyrowave Cr[\(i)]"), + let cb = plane(cw, ch, "pyrowave Cb[\(i)]"), + let cr = plane(cw, ch, "pyrowave Cr[\(i)]"), let offsets = device.makeBuffer( length: max(newLayout.blockCount32 * 4, 4), options: .storageModeShared), let payload = device.makeBuffer(length: 64 * 1024, options: .storageModeShared) @@ -585,6 +614,7 @@ public final class MetalWaveletDecoder { slots = newSlots nextSlot = 0 layout = newLayout + hdr16 = newHdr16 return true } diff --git a/clients/apple/Tests/PunktfunkKitTests/PyroWaveDecoderTests.swift b/clients/apple/Tests/PunktfunkKitTests/PyroWaveDecoderTests.swift index 8c28cd15..5aca89e2 100644 --- a/clients/apple/Tests/PunktfunkKitTests/PyroWaveDecoderTests.swift +++ b/clients/apple/Tests/PunktfunkKitTests/PyroWaveDecoderTests.swift @@ -57,7 +57,7 @@ final class PyroWaveParserTests: XCTestCase { func testLayoutMatchesUpstreamBlockSpace() { // init_block_meta's walk for 256x144 (aligned 256x160): level extents halve from // 128x80; per (comp,level,band) count32 = ceil(ceil(w/8)/4) * ceil(ceil(h/8)/4). - let layout = WaveletLayout(width: width, height: height) + let layout = WaveletLayout(width: width, height: height, chroma444: false) XCTAssertEqual(layout.alignedWidth, 256) XCTAssertEqual(layout.alignedHeight, 160) XCTAssertEqual(layout.levelWidth(0), 128) @@ -85,7 +85,7 @@ final class PyroWaveParserTests: XCTestCase { } func testDenseParseFillsOffsetsAndCountsBlocks() throws { - let layout = WaveletLayout(width: width, height: height) + let layout = WaveletLayout(width: width, height: height, chroma444: false) var au = sof(totalBlocks: 4) au += packet(blockIndex: 0) au += packet(blockIndex: 3) @@ -273,6 +273,17 @@ final class PyroWaveGoldenTests: XCTestCase { try assertMatchesReference(decoded, prefix: "ref-chunked") } + /// 4:4:4: the chroma components run the full pyramid like luma (no level-0 skip, no + /// early half-res emit) — the layout + dispatch structure Phase 4 added + /// (design/pyrowave-444-hdr.md). The fixture comes from the 4:4:4 host encoder; the + /// reference is upstream's own 4:4:4 decode (full-res chroma planes). + func testDense444GoldenFrame() throws { + try XCTSkipIf(!MetalWaveletDecoder.supported, "no capable Metal device") + let au = try fixture("au-dense444") + let decoded = try decode(au: au, chunkAligned: false, windowSize: 0) + try assertMatchesReference(decoded, prefix: "ref-dense444") + } + /// Phase-4 partial delivery: zero a mid-AU window (a lost shard) — the frame must still /// decode (blocks > half) and stay recognizably the same picture (holes reconstruct as /// localized blur, not garbage). diff --git a/clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/au-dense444.bin b/clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/au-dense444.bin new file mode 100644 index 0000000000000000000000000000000000000000..6506e5ae04db7599f1ab0131e562bbd84352d837 GIT binary patch literal 65452 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[X\]WZ`]Zbaa_]MNQVOSOTTQONMPOThfdgaijcimcfmpmoXY_]]Y_Wbaaa]`bbpolqqvwpqmpzpywykgcglhjjhkhgjjgm|}{z}z|nnwsopxuovzv|||v||PKQPKQSOJSVOLMVMEFGFFBDEB>DHFJJI\ZTVY[YY`V^Z\^baLLQJKNLPKQPSNTORbchfhdccdfjideik^[_`Y\X`ZZX`\Z]^rtumttqrxpmuztzvficdicfiigohmlhm|x{{}|tmnsqpptqusyr{|r|}}z~~~PIHPISINKOPQPQOSG@EC?=CFFGABEIHDY\X[^V\]^Z`]^V__NNKIONPUULPRNTPR`adefkh_hgkffekfUXW^]V_\\]^Z_Z]drtpqqutrrpptxzsrffegilldlhlknmfhyz}zzy~y~pnpvutsprwxpqssz|{|~|}}NMNNOGIRONMRNJUP@F>DD@DEH@GBGJHAUS[YX]\TZZ]]_YYWIPMMRMOPQRNQMQRS`b`b_g`fkfclgfmi[XZ\T^_Y^\Y`YW\Yipmtlvutqtwswsvwifheakcgjjjidief}{~~x{~||{~pqsuprpxqtutpqv{~yyz|}|||{IHKJIJOPJNSKRSOOE>ECC>DBCCGCGHGCVUWVW[[Z[[U^W[^^OQMJNMLOTILQUQNQfifg`b_di_ghfbeeXZ^W\U^WZZ[\X[^Xqsppllttqqqvqqurhggcfacgghifglfey}{v}}~~~llnotqotopqrsrwqx||y~{{}zOHILOKGHKJJORRRN@?A?CAFEBEABGGDARXXXZXQYY^[^UZWZMMNGJQKLNNILSOPQdfad``bfcfjefgkhTUU\T[[WXYYXW^Ybknsomrkoporqwqnv^fe`ee`hdhkbflhi|ww}z|x|zkntltnpqmquwvrsux||y|y}|~NGFPHLLLLOQMKOPOA<==A>=?;?;BA?CGAC;<>=DBADMONMOQRTPPRUWVV\KEMJELEGHNJQNINM]_^]Zb\_e`fd__aaUQYOXWVZUW^Z]XYWhhnefqkomqjqorrq]abed``bea_`cbilrv{r{yz}zzxuv{kkomkrikprplpkor~t~||}~}xzyz{|y9644999<;67=?=<8LHPPQQMKOQSNSNUM@?FD>CEAFECGDGAGS[[UY^W^UWWY_[a^NRNSKQNUPKPMLPSPca_cfjcgfgchiefkTT]W]_Z]_`Xa^_b[oprsvsqlqqssrrzufcbabbihjnggjhhjzvy}{{|~pptrprvpwrussp{{{zzz|}|852::53368<<<575GGFGJNLPMNNTMMSM<>@GDA59IHNHGKOGRMHRONKNAA=EFBB>D@EEA@CFTSTWY\YYTU]ZZ^`^FHOPNLKQMNLRNUQM^^cbaaaf`fjfcdidZ\UXYYY_``XZ\a`Ymqtnntmoovkwwqttibjeiiiebbedjgify~{w~zzz}|tsttmwsnxuwqtspr}|}{{~{4362700499889:5=NKGOJJIMHGINMKNN;@A?>=B@CA@EIFBBUSWU][V[]]ZY^_V_OONPKMLPNKTSNOSLdcb`b]_b^jciibjbUS\YWWWY^^X[a``]sokkornqnpuuvrtoab`cdedhjijhdekf{|v~{|y~}~kmmrqunluvssttovz|y~{|z0187:308842588;>CCA>BNVRXVSZRXTZTZS[XDMJOLGFQKIQIOJGOc[[^_[ebbdac`_hcWWXWSXTZTW[ZY\[Zhphninjqoptmpstsc]d\bgedhaddedfjsxzzw~wxyy{{w~niojojqqlqnjsvstu{}yy{y~{z{}|~.2-27-48--/33361DILEIGDJMLENHLKL=6=>;@=A==<@;>ADRROUPWQRRVURQZUYGEDMJGIINPLIKJKLY]c`bb__bd^ab_g_YXYSRY[TVXXTYZ[Xdijpoppmnionmrqmd`d`a```dgbgdhjcxytu{v|tzx|y{{{{jipklqimkkkmonlus~uxvuzxw|zz||~02-135-50442.712A@JGEKJMKJHNGGIL=:;?;>>AA?BAMTLQPWYNOUWUSWXRHEFFFNEJMHLIGPHJ_bb^^d\`e_c\f``_USRQQTSSUUSSYZZXhkljngpoqhkpmoqn]^a`f_bcf^bgdbchtzxwwwy}utvxxwwxkkohfnppoqtuslnq}rzszy{{{wz|yzv}~}2403345505138558ABGCJLEIJHKLFOND@>:AADDTKRNLOQUTYQWVVUVCGKMCIEHMLKLHEERY[\^a\`]`d\e^aadSSPSXWOWWUX\VZYWhfiekhofgqlmlkipZ\]\eZb]da`cdfecouoqwqqtx{yxwzxjehmnqmiipiqsktp|}txzxxv{zyz{{vw~*)-.24.-170-.167>AIDGDDAJDBJHILK9667<7?@@<@==D?BUNRQNTRWNWQWTXUTAGJDKCJELJLMJKODWVZZ[a\_Zab_ade`SVRMRTPXWQRYQUUTccehfmhmieklgmkqZ`Y_Zd`^]`]f_^afvnupypusw{xqsx~xjodjhmflqpjkiooqz{}~xwxu|qysxwt|y{~y}~~~-*,,,,0+-*3..035DA>AEGDFGDFAHIHM596956=6AA?>@;?>MNMILLQLMPOUSXTPBAAAIEGBGLLKJHIJ[[W[\`ZZ_a^`_`]^PNPTONPRSRWXSWOZefihfgimfhkohopq_^_\ca\__`_]^a_arqxqswowttvuyvsxjmheenjolollkmnk}~|}~nqyxzxzvz{wxtx{x0+(./*1)*,++1.-.ACCED?EBJGECLBGB7=4@5=9:8@=;:=8=MKJNJMMSUUVUOVSTCABEIJIDCLFCJGJDU\U\Z_Y\[bacZaa_KQOOTOVPPPWTXPSScaecelejellphlngX_``YZ_dabdb\c]]nmoottwr{txtrts|igiciohmhnopqnpj}z|~~}vvxwqxtvzysuwyxv~|}}(+/1,*,-20)4.-3+>F=AGCEIFAIB@GCK7:87;6;<9=89?>?@=>=>2/41556//1011433@DHIFJMKFLKENGOJ7=?:?B?D<:F=C?B@UUVRPPQSYVQSWYYXKLGENIINGHPHOHPI_\b_da\ec[cfg_faQYRTXVZPR]TZVWY^heopinnhqnppoknl\^^de_]f^d_bgehiyyyprzrz}x{xy}ioliqqrqnrqrtmou}vst|zzy}}{|}:6;:7<>>A=><:B>B0/41/0446650/332CFDCDBGEDKHKIEHG7<?A;?@@7=>@<<<-).//540--657659DGFFFBCDHJKBGIEQ;>:@8@>LNRMNTQSSQTSQUUTGKCHMFGKKHGMMOMPX\][]_dd\aecb]]]QRWXXTVYVTYUWWVYflcilfmjllphrlpkZ]_aa`fcdgdhfefcyrpxw{qv|wt|}z|jhglmjllpollqmpq}qwy{yyuuvx~}z}{y~8<48>?7:9><=;?;9-+2/,5231411402.IGDHIFADJDILLEEH;?<7;=@9CENQSSTVNUSOUTRXVZHKEFHFKMFLKDKLGF^`a^aab_`]^]_be`RPXRPPWWTTS[QVXVejidfdepnjlignkha[]_b[cb`fdhcga`yuvqzx{rx{{|zy||khhmoprhmokirjkt}}~~~}uzwvuzwx|z}x~x~1678899859A99<>;(/.,.*/20+0...0-?DEDBGHCDIIIGHFH8<9;@==>A:@<:9@;TNTRUPMTSQRWUYWU@LDIHDCHGIECKFMGXXW`\\ZcY][e\ac_MQQNRPNTRPRUTZUSbggdcjmkfffohkmhYa_\b`^`bbc]egc`wppsywpyzysust}skjknknmgmfrnmrnt|qvuuwxvuwuxyyxz|~;78985;864?8?=AB/23*+335,,/11533AGHGEFCBJHJHDMJJ9;7=A:6><<::@>A=LSLMRKPQPRPVTXZWIBAECGJJFGFEKOKH[ZZXa`]][b^cdb]]QMTNOTSXUTXPUZTTehiljnjhofjgkqgl]XX`ZZbce\\faba_unnrpwtrutrzzvxyhignllhiokjrqlrr{z}xxut{z}ztu|z}y||~:766496;=<<886=A./)*231256/152./AC@C@BCAEHFKIJBL6<:9>9<9=??@D8DAQMSJRMQQQRORSUVREBBEDJKKGGHNDNOL[ZV]W``aZ_``\_`bKOTNRUVWVVTZXXTScekfabifkfiejgqo\Y^Yc`[^_^c\]_a`nuotsyuwzwstvt{vhllleqmjihigrljl}|qstrwswx{zvx|yzz;:75327;;;5>>76>1+1-0/10-0503572BD@FADHC@FAJJJHG9==6=:@>7=@B>>CANSQULPRMLRRQUSSMCABGFJEHDEIJJKFI]\ZYX_X[XY`][Z_\VUMXSUVUVVQQTSZZjcihhieejkngfomob_c\`Zbb_^a^cc`doqvvuyvuwutsvrusmoolhenmlifjlonl}{~~}~xwuqrszuwxsy{|xu|~~21246567<;6:69;=(0/0)/44+-,/0/45@>GD@?AI?>AHGEGG688657@>==@8:=?EJOPJMMOQWRUNOMTPEKDAKIHIJGGKMMIKW[SXYVX\_Z\[\Y]^STOUONNRWWUXZVXYjgeebggmbdjcgilo]ZXb^_]`_]^daa^hpmprvwnsvwsxyr{tkkmojggjhrhjmpjqx~y}~~rvtuvzwzywstx|vv~634679;4999>7:5=.1/,*/4*,02,.3..?EE@A??BDGAGF@DG856;69@:=9:<8AB?LJIOPNQNOTKLTPUPEADDABLDCEKLKHGO\V[[U]Y\^Y][^Y_aOTWTNUWVOS[WRQSSd_dhcdchdcgnkddl[_`Z`^aa`^d\`beftmqloupqotpupwurjklogifpnpqmlnklw{}{svqtszq{yx}wy}uw|}7496769162<79:56/0.-.20+04/6../1=@>CFE>FADEGEH?B4=7;769=<7?><@?AKPKLLPJMLPKNVNLUEIJGBCJECNHIHDFKYTWYYX^ZVZW\W[Y`OWNSLUUQXVUQRSVUibhfgfbjheegeidkXb`_b_a_]\c^^afflkquovstqwpwouzpmkfiljpfjlmoppplyyxzz{}{}|~ytqtuws{zvywx|ww~~219222834:5:9;9<+))1,+3+0/62,448=A@EADA=@BGEEDBB779<><<8>@<<><8@MGPKNJPRKOMOTPOM@IKJGDBHKHEHLHJHUW[YU[Y\^V]V_X``NPUONWSUQSVQWWWSee`gef`fdfhijkfl\[^]ZaZ^a\^__]^cmotnoutpmvvovtuwfmhcepkkhmkljksny~|{|{}~||yszyyvvtrt}{ty|y}~}442/1358:3:4355=*(,/1,-3/..64116C@@?BAC;F@EA@A?C::;;=@=<9C<@@?E@BCD>B=9756<:@@9::9@B:LFIFNMLGLJHOMKNSCJFHECDFJGLMFGJNZW[Z[TTW[]XUX^\]VNUVLONVWQUQRWVVfab```bgbghkhibd_Z\_Z]]Z\ea_\a\_qiknoponlouutvnteiggflogiqhjnkimuwz~}z|vvpqsxyttuwyzv}{~24/0635505752871/0.*++.+0+425,3.>>?;=A>E@=><:88:;@?:7<@8B9LIMNEIGLHLPHPHKMHJGIEGIHFIDGNKMGXUTTZY\YWXUZZTYVQSMTTNQYWUQSWVOYf]^bdfab`aacffcjXba\^e`Zfa\[]c^^qoqpkpqimlotuvqndggiimiggnllnmmkxy}vv|z{yy~|uwvtuxtstwvvttz|~+'##&+%(&/(.'-+,956<=3;:899;;>>>3601128251282:43BB?@C@HHFFBGJCCIC9;;@C?=EC@AHBGISQPRLRUPOOVNTSWRLOMKPOPQQOLROPPRW\_^[_Wa\b\Y[`_aWOSYZVYZ][ZY^[`^gjhdeckhlneinjoh_cgf_cajhd_fkhgitxtrnwuyuvvwxvsypkjtkksqulnmnwrq~|~}~~~|z{x~x||#$*#"*-)'-*&&0(.339193<;9689<5;=68647586880789<;CBACCFADEFEHBFFI:?@ACBAB>E??B?@JNOKJPQJLSTRPQSPGHMGMHINOLQRSJJQXXXWUUVZYW\^ZXc_TYSTYYU\V\WY_WY^fggaabejlfffhdfeb`ebd`heecgahkgiqunvptwvsxpwqruuonopknkmntosorus~y}}~|z|z}y|||~~%"'&$,)&%(%*+)(-5334484446=;987:5648/068:7;544:=>F?B@A?AHADDCHEE==?ADD@>G@BCDC?DKOMOJOSRQRQNMMVMMGFGLMNQQOSRRJJRZWXUUWT]X]Y__[_bRZ[\]ZUYZ[YWYY\`dc_bfecklkgimige`ageiea_dfkegjghqqoqppsvtsosqvzxqonqrvtmtuuvpstr|}x{~~}z{{}y|}{~~% #%#%++(,&-,+'.00/68399:797836:5626/3975166;257>>>>BA@@EFIHMRMIOOMLTLTRLGHKKIKJNQMOQRQPPSRYTT\ZZ_[[^`[\ZVVTVWXZZ^Y[ZZ\\\_edd`aafbliecfhhdfhbdjdeigcadhddnmqlonqwtpsrswvsmqrokoktnntuouvpv}~~~{|xxv{{}{~z#'+-)*'(-,-.%--014916116;573:9=363321475267586:>;?ADC:?AGBDAHDCC@;BBD?;C==CHEFGEFLLIPLRGJOLTJNNUOLEKNOOKHSNNIOPS\XUR]\V\^U\VWZ[[ST\[ZXXW[V]][Z[Waecfcfgdaeejiicfbded`ffdkbjddgdissmotruwtmorwqwvnmlnsjssmqvorrpnw~|~||~|zxxyzzy{{})+%$%,'#,$.0%,'+//13/478617294353/5.88763:436542<=<=;?ED>BFB??@H?A@;=C=CB>CD??@@JDLKHMLNLLOJKKLJFLJNNNRPPORQKTRNWWSWTY]^SZ^X[`\bYTZVWXZY\V__\X[Uddafdegdicbihhbjgc`ideebefa`ejfgktlqqqusppsrmvqvommosqmqqtnwnoopyzzwz|v{z~{~}|ww|{}{~z{%%&-#!()%&'%/&+-254310156370:76754850385451<<3389??EABDC@>;;CCC@A>B>AEDEDNMOKHPJGOIQHPRRLGJIJGMPLLMINIOLJUQSUYXX[^\XYZ\\[TW\YWXXW]W\\\Z^W`_bgca__hechdfggb`f_ddfefeddghhkslsoqlrorsssovsunpoqssunwoltwsprwxvwx{y{}{}tw~z~~}|zx~|%",$("&&+,+&'+(+03146359851:66241272437542445967>B=:=:DA>:E@CE@G>=?=C??@BCFBGCC@HJJGHKIMPOKIIQSTGJNOIQMHGOMQKNJLVQXSWZYU][U]\Z]YWZWUSWWU^[^\[XZ[f`ceaffacfficbgfeage_adff`adedehpnmismrlprruquutnojrsqnvslutwqstuyx{y|{y{z{}{~xxyuy~zz}~~}{'%)*"$$(+&,+-)0--50-510379240884-630064.833734=;9@><@@B?CE>?BAA?;@@CDD=?FEFIDEKJJJLHLGOQNNFKNMNGQOKPJOQKTTWUYWURXUVZYZTZXYVWSSV\\\[WWYX[\Y`^`b`caaac`fe`bebcgceegegedgfedhpjjjqqrrottjqnrqskukmlkqsntqqynsxz|}|{y}{zz|~~}}uvxx}~}}~|{|$%''*#%'%),.*)*.5.17354..3-2370154325446844<388=<>96;>;:<:@DDE=?::;?@EAA?B>BHNEGGKOHHKLGJKJKJHLKGKLOOHNMJMNJQVYUYOYUYTXY\^YZ[UX[VUYZ\UX^]V^_Z__`bccafee_cfehi[`c_faeaghfebhkknlnmkmhoiqstoksnonisnroqwqqtwtport{yvvwy}x|}~{y|||~~~{wx~y~{~''#$+()-++'*)/)*--340.30/7562083.0527985736552;9;99B<<;9A?@EAB;@>AC>B;@CC;E?=FHFICEEKKNHMOFIPIIPEGJIIMNNGQHRJQORMSVSSWWRRSSYZXY]XSSSVVXZ[YYYY[V[`]]a_`bdefabdecibefa^gcaigiighejkgiilnnpqqoqnnssrmkqpluomruspuvuzxxzyzxyuv|ywz~}~{y|z{z|}}} ''$,)&,)-,+++0//..14+243423.112/2802639127;68;4:8@=;B9B=:5;>:87;?;A<<=A>?@A>EABBDDGEEHJDDKMDHKKNJFMIFJHIFPKJKMLOPQPRVRNQUTQTPZSUXZYYWXYUYUX\W[a[WXZY_`\[`\]ae`_cedbaeedaedfdhfeieknjhdgmnjmkjoqiqjromnmmooosqsorsvyvttswzyvz}yx}~|y|yz~z||}}~}~#)'',(#*$%'*/((*.0,*,.0/40512410/2655480037674=75<885:>>9?9@@9;BB:==EC@DEBAEFJHEGMHMFDGMGLJKIHNHMONPLKPNQMQMNQOWNWXTUWXUSYVXYTVTW]TX\W_Z[Z`^`]cbcbd^`^cdfde`cbhiceedchddgfdfgnilkoomionokmkmojqqpomqoopsrqtxy{|rtuxv|}xwvyvxwz{x~{~}( *)(+,+((*&+,/*(+*)0-/14,0,-43134637360123=34:75=:<=;5:=A;?@;>@=;@ACB<=;E?=EB?CEEFGF@IJICLFKJGNGJFIILQMPKLQRLMKPSTOMSVRWUSSPRRTQTWUZYWUXZUX\U\Z]]a_\Z^]\_d`da_b_egeebgibhcdheeelihigkfmjmijjqpnllkkrosrqnmrssuswttxsvur{yut{yzyx~z~z~~|{|||~ \ No newline at end of file diff --git a/clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-cr.bin b/clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-cr.bin new file mode 100644 index 00000000..0613a5e5 --- /dev/null +++ b/clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-cr.bin @@ -0,0 +1 @@ +qqvpnqzupsxvst{x~zw|~~}xx{zĺÿqsxwqouq{touvttqxww||{wzzƼǼ¿ſɿttrypprwzyuxpuzquwwxzz}vy}||~~~ǹmotvqpwvstqwtsupvzw{v{uy}}|~~y|z}Źwqtqswossxsuuqpty}wwz}x{ww{v~|vz{|{~~¾ºunkvspvwyrstqwtq|xt}v~tz|z}|~yxy{{¸¾Ƽſtnkluqrqtwwlszpqxv{wvu~}{~}zw~|~Ĺjospmpsqxupwtysx{rzvt~{{s}yv}z||~úottrkrntppmplowlwzqv}z|vw{ysuv}y}}Ƽpnjjvqvvmqtoysovsuszqtuxyzzsy{y}|~}½ÿnpmnirvlqusmuromqrxz{zuzx|}wztx|y~|ø¿qtpjrumqtvnpuwwmtrvwxuywwuw|z~swy{y~z{}|}¹lsmsklsmpsnwonlnxtqsxp}uxvz~~szwx~|zxy}}~~~~Žigrjuslkqsnurqorpw|ysws}t|{u}w{}~||z}|{÷olmpjunnqrnljotqzworyzv{r~uzytsw{|y{}|}}|~÷½hqjpjnjstvjhkpvlsyx{uy{{pwuxuqw~|v~~~zy|~~ÿ||}vknljoxnptuuutqz}xy}yzx{v|zxwu}}}~||~~~{~}~pputopsorpkomvms{ux{{ysvsvy}~v~zz|}~{||}pnjruuussqrsosxvvsxsqx|yt{}y~v~z{{~~~w}}x}~|}rusrkqjnpnpwmtwtxsr}susyv{uyu|~}|}}}|}~~|z{{~z}z}}z|}lopokknqopwqptvwsux~{yq|x{ss}|v~|{{~}tz~~{~}}|zoroorkoltntjloqmyssx|rryxvw{svuwx}}y}{{|yyz{y~{nrjjqsiokuqlsssvwptquytz}u}xwzyswzz||}}yv{}~}ypkqkmtljmnljmwks~{rotvxtvqqvy|szt|}xz|xz}{|{{}yznmniojotklsrokskpqpxpqsyq{zvsx|ux{{z}{~y~zyx|xwx}}yx~jporjiihooqlojmr~stru{wxsrxzuutypx{~|}y|{z|z~~~wz}~|zhlfinrklhlkrnlqiqsrwspsxqnqqyy}rxyz~|~{|~}vz~}}|||{mkhkgklrslpprlptwrnqxrosxvyswyw}y~zwx|x}y~z}ywy~zyv|{z|}pghlgjqslkihuosm~ssvqzupnwsvpuzu}|w{zxx{xyz|z||wttzsxz|y}gfjqninooqjhgjlm{~}tvsxtzwtrmsnuspz|uzu||vzyww~uts|~wvutwwxoojomhmnnrismrgm}}~pusnnzyyrnuqyqtu~z|xzw}yt|~|{x{~~~~}xu}t}xxw~x{w{}icjeoekmglmkoflh~pttzlutrusrmrvvyv|{xwxuvzvyz{||db`ghbagjhfnikhev|{}y|injormnsqulnsvjw~ozzswyprvtu|qrrz}y~{|~~{i`jbg``jajcdifmkw{}{y~y~}pskqssrrppjotmsrnzpzxt{twrxxvw}s}z~ywz~x}bb_e`gajhbdbchgc||wxkqilhkjknopuslun~u{vysvwuqusqwtw}|{}}|}~x}|kijegkibikcmgiecwyw|~|yokqjqpmittslkpnowzqy{ytwrrpsxs{xxywx~x{zz~^_fkhgbhdclbimkjvuvvz{y~|z}|ooqkhjjjjonqlojo}oxvvuyvnqr{ypstx~x{wyw|{wyz_eeed`agbkcjc_ef|zvx{x|zyy~z{frkqqpmroqllklos}~mvuxxopspzvwqvqx{y}u}ww~}~yw~~`h_i_fbgcc`jdccjuxtuzz}zwz}kpepoorhlmikpltt}~tyrpmozpunysoqys|vu}zu|vzw}{y~|}hfa_^`dcbaacfffe~~zy{tzzw{vyvgplkiplnfjpmolrh~}}nnqpowwlxzuuuqsz}ut}|tzw~{yx`b]bf`faaj`eiakjtwzvwvxzz}yjlfiehoiogiilkir|}}~nsrqvorrptutqxtss|x}vtv|v}{~|}~hdhi_dcjd_a]glcfuy~txvw|xz}zxzknddefniljrgkkni~~|~~~upqvpowmmysqmxn{}uxzy{~xyzww|}}}e[f_ghfhcbgdd`eayvuxywxu~zzzxzbkhinhihioeogfhh~~~}qqnntotqrkrtysxsvy~v|t|~z|v{u|~}~b]e\`abebcgccfbbvtw|zvx{}{vx{wumkdlggepplfplnmk{|}~{~}{}}qkrkqntwmllmstvqptyxu|t|u|}zxzz{~}|}{^^^fa]^_ba_cidddrry}uuw~xv~{zwxjgijfkekpdgkgmjsy||kmookkuqwlmouvqyrssv}~tuwy~{~z}||}{^_]_d[ga^be\__h`{}svyz{~sszyx~{hndimkodkopngmqo{|~}}qqmnruwlrlrtnrvozqsu}xs|{t~s{|{x{y|~{Za`db^`afb]gc^b_}}rvqw~v|w|uxjnddehildfefdpjq|z~|z~{ntmlotrkwllulntqw}vuzv{s{xzszvuz~y|}}bYee]fa_dd]aafef{qs{}zuytuuwz}x{ihjcmlkglgmmffim|xz{}||qutmuutpqppssrvow{{yvry{uut}uuu}~ttnqmlxryoypnrvygb_`abaafgikckblw|txxyx|{wpkipnmpflifnnmql~~vxtolwvsqvstyxuz{|wvsz|w|zv|{}}~~rpototrqnwzowrqu`\_^gijibdbjegf`x~{stz~{x{y{}yz{mmljhjonpprtqnrm~}}rlnmlnxxvrzppnovttx|wy~~}z}}yw|~~vtwnmvnorvoourwx_\c\eei_ajga`gbc{~wvvy{~~}~yw}mnjdilnpggooppsr}{|}{qvlpnptxvxtwqor{}v|uyv}}z||y{xwz{ppvtnssrnnqoqpww_a`c_`^cafhagdke}zsz}w}~sxvzznfhiljfjglnmqjpr~{|||jrwnwrotvtnvunnr{sxty}v~z}wz{z~}|}uokwpkrvtupyllrtc^b]ce`bb_`eche_wsryurs|wtwtz}vioileeeeirmijpjn~~|}|~ppumnvvqlnmvtynyxyrvxx|{zy|u{{y}}{~kjnkqmoqomxunwwqbcdb^^_e\`^fhijdzvw|zwystvu{v{glidjghofkiigggozz|~}}kpnotjnxunvqpsto}|zs||x{xuxxyzw}~z|}nmksopkoovwntuvu`dc]a]eeah\eiege{vsuxruvvw{ztxdddjkilnnhfmlfjp|~||}{jnqssqmrpluwoqwmrsztwz~|s}vzvv{y|y}~|ilqrsntvlmnuptmsb]^cb^f^g`fa]bicswyut}r{u|tstvztjkefgcbheldlpilkyy~koilllqumsulsqvwur}wyu}ruusuxwzxyzyy{z~qqrnqlqosppolwrv^b_bf^\aed`bhg_`supq{syuuvvv}yvm`lfdcankkkkokneyy}{z{|}{jtqkukkrpksruoqnrtru{qx|xwtxt}s~xz~~~miropjkvrornpplsegc`dbb``f_^`ab`qt|xyz}uysvty{yfihfihhdhkonpjkkyyw{y~{}|}{ronluorlrnquktspvvuttryx~|r}uy~r{~yz}lljlokiqokoismnpad_Y_cc\[Zf^\fderwstu{yq{u{z|q|}d`adjffljkkedembx~|{yx~~{~~}hpsipikktqsqsotqpyqtrtrqs{zq|{xvxz|zy}}|yzinkpkilojotolojtdbc_\_acZ\_dfc^fyzxt|t{v|{|~uy|u_af`icebkkhglkhh{}zv|xxz~~lhtijlklouljmkltoqtsqpxzuzzxty~tv{zzyzzx}{~~fnhtpoqmhlmpjjnuWaWa^dY^c_e[c]`csqsyyu{tqxysrsw~jhehcbgjbjjehicl|~}vwwy{~hgmshsotskjjpomrtnysqprryqqx}zqv{}}}}|gokqlhhpmriprktqY``Y\\ab_a\c^]bfxrvuroqvptr}u|xr^cggcbbhkkicgjkkxyv~|xzmljimimnmpsjmmkk~pmuwxys{yuupsvwt}yx~}~|}}z{}fqqrmsilskqprtmra_a\_^_`][Z^^_e^yrywvyzsqrtxr~|tjgcaeihhicecjedf||{y}{x|~fnhiphjihmmrsqonysoqpxpvznywq}rw~u|w|}|y}z~x~phnnliqjmghnhkqmXacdc`\[bX^`YdY\wvqupyszrzzyurttiihegedgecddifceuv~yw}y{{plpqkospokoqjmji{qqrovtqyy{yvsrxyx{z|z}www{|_]VYY]_^[_`\UX]Zplknkuulomkutvuo_eZc^[\ch_`_gfeasstx~yw}{}zu~zilkfekffekifhmpg|||~|z}~{skprvjttuqrpmomp{|rs||xsrtsuvxy~yx{z}zz~{{|X\ZVQUT\YSU\VUVXlvjllkunjprtqmxucada[ZZ`baf`\ebcqutu{qxz{wx|us|efbehcnhidkleehh}~v}}~zzy|~nkjkjutsqrqnrutrys|p|{vpwwu{{|y{y||z~|~z~V\YVU]XWY[[T\]`Zshqmqomslrkuklqucbb]^efe_]_b__^dr{yrpxvx|ss|t~ythnjmcmilbnfilkll|}|z~}~}npilintppupktrprxyyxrtp{uutzz~wvz}}QX[YYVYVTVTY^V]^mkrsshupntltoqjub][adcbb`^\bf]hgsvuwz{qytyvzyv~|hefjmcnldecnfegq|~}|~~}hkoqmqpslulnlorup|qvsuwyzyvuusyy|zz}|y}y}WXVSSXTXV\TYR[ZYhlsosuprouqhvrquYZ[c[dZ_dd`][dfcppssswqxwwutw{|uii`mkklgbkkfddik}{|y~zy|oqkllrthotmouvquoutztqvq||ytv}xz|}{~}yZRZZXTW\\XRWXT_XmrhjjihmipnkhottX]_b_Zbdcdda`cf_ytnyptt{{|xt~zvtbbcdbjdmbmhhkemfxx{z|z|iphqjspsiuikuosrovwzvqvsttsqwy}y~{~v{~zz~~QUPP[Q\ZX[TVZ[R]qqlpipgrqrnruunra`YW^[be`^``ecbdyxuvstxvrsq{w|}qgh_ifgmjijhdckdj}wyx|}yyyz|~{mhpnjsntmjtkmuotssuxysszwvuv}s|{yzyxyzy~PS[WUXU\RZZVZUW[jmfnoqmoitljjnolX_`bVX`^abc[Z`b^pxsurxqstsvxuzyukf`cgafglbcilicbx~uww{}~oqfkqqlsjlsqtmto}}qxsw{y{xvvsx~|st{y||~x~x|w|WZRYXQYTVUSQ^U]RmejlpjjkiqrnnorpaaaY_b_b\`cZZb`_vnwvuwqsupywxys{fbbieajccbbgblmcuvxx{{x|x}phokjfhrmqpqpgnk}qnwqnqzqvyvyzsuxyvz}ywy{}TQYR[WZWRZVU[UVQjhpjjignrmsspsqlZW]Z\[Z]X]Za]Z\[mxnpnxxp{vx{pyv}^eeh`^`jb`afejcbvzvzzwy{|zmfpkrjkpqqhlsslo~~rowrxvy{opsv{wu}}v{|~}w}}VSRXPSTPYPXUV[YZngkfkenomjkqjgqmZWb_XVY^]bX[Z^Z^nrrxrwvoytoqxorrc`ahfhfahhljidefvzuy{yyxzekeheqhgjngngpsl}onumvooutsyswtuozv|~uzw{|{y~~~}}TTWVPMSVPRQ\UZVRhhflpnflpqrjqmjg^\[[\\]bcXbWbbc[vusmvnxmxpxpzutq_cg`edckadcficlkuyzuxy~x{{z}|nkdjpmjjnlimlspo}~xttmvluooptvosytswxw|xyv}v}|}y~SUXSNZSTYQZWZ[\Tofioonpojoljkpgo_Xa\ZYW\__]b_ZYZtqnwrmxpwytrzpuvdfd^a]ccaiehdabb{zzxt{~~|xxxwzyllomqoiijhnhgonp}{}uuskoupwmtvqxstuxwxvzxw~~{{{{~x}~}~~VVRVZORTOPYYPXTSjdfkilgignospkjkVWV_`^[`Waabbba]uonxvvuroxmnpowzdge`jc_bgahcaia^{zyxzwuyzx|u|ggfnifihooooplkk{~~~}}~lspxopptsustzqrmv|{susv{wv}zz}}~VXQRRTPYPRURSPZShfhkemhkhmoknkil_YW^UT\Y[[aVV]bbvsswonoluwqoxuut^bd^h`f`a^`ffafk|}|uz|{w{vxyyw|dlphkiophpopkgpo|||}~mrkovquoqttvwq{sy~sx{|y}yu}xwwz|~|~UOQSUTRVUUQRRPROfglhfikknffkfnjrYS\UZWV^a`X]Y]cWumvovrnspomoqtnr_hdad]gf`fedgdedv|}uswuwxzu~zweflmmmengihmleps{}~}rrnrvqnmrxuwuvqw||t|zww|}}~uwuv{{~~~kica`ja_gkelileeQZP\\UW[UZZYWV^YfijhnqknisopruunZ_W`Yb[X[d\_Zedbpnptopqswyysz{usdhfb_fbhbkglglil}z||~xy~zzniqqiklokoqqmiknqrtuqpruuxvxu|qq}z{yz}y}gf_dkg`g`iicdblbRWO[YTPQQ\UUTUR]fpjkmnklhmisipqpYWb^[b[_dX`b\ed]qwopxvxs{ovqurpxdcijigk`bdfmiafm|yxy~x|zx{}wmleijmsgokmmlujj~snsvoq{xqxxxuzsrz{}|wy{{|y}{x~cia`d_k``ffjcgigQWXPZSZRTTZUU]VXohprkjonjiipltriY^U^_Y[`a_`aX`d\ytpvqoqyutuwxuyuggcffjhdkehh`bld}}u~z|{}xy~yzejilniknkinlmrlm}snsxopywpxvtrsrrzw{}yxwx{{x~~ccie_bgidl_ijkfgQP[VVXOQVT[SXS[]khjofrmhqpqjjolo\[\Za\WZd^b`dcabnqsmvouotvwvzry{db_^bijchkjjhjkfx{x{x{}{|{hfmqihkqlokisptq~}xqtmttoqs{{z{vuy|z||zv~v|~ywx}}\deh^i_hcgfigjchQOQUQQPZY[UR]]Q[knhpinggkfghmtrkZZVY^aW``YZZYXZXvvtplxrvs{ztvyq|bde^ajicd_cadhbi}}vs{}|ywyz{y}oklmmnpjjrgihnnt}~~srxuqzmtywoqspsw}|x}y{{~}}yz|~~~~a]a^eai`e_dcejlePUVOOOZXVORSZTRUgglilmgipmjrqrnlW^\b]Z\_`[YYWVY`sssonuvnwvprx{xzb]ifd`f^igfj`fgixvtxyxytvx}~okfgqklnimkgjjgn}|~klvrnnvsmtyszyyq{zu|v{}x|y~x|~~e`ie`fic_hkb_`j`XVXXVSSUPNRVUZXYnkdgjljjpeojkorqVW^TVZU\T[Z]WaY[ootttpnlotuuopsufdfh_b_gaa_gc_ad{|t||yyvs}z|jmfilfjklirjpnio{~}}skmqonlrmrpwny{nwwws{xx{|~vu{|~}~~f^\f_i]b`ddfeeajVRVTNMRVWVPPSXXOloiloemnnkqnoeop\WXTY]Z``V[]X_Z\knqssvrnrsxrspvq]a^fe]fccdf_g`dk|}xyy~{z{wv}yyjjijmpohojpnqqfh|}}|}|qmousrqmqvwmnqpxwuwx}{yv|zz~vyyu~~}cddde\]gddbhb^jcRXMUTPTVYOXQVZXPfclkionejlnnphheT]XZ_V\[^^[[W[\^mplnksmqypoysqytb`bd\fg`fc`i^]c_rzv|s}y{{{~mklgdoghnmnleleg~}|}oqstnqoxostrlpsyytruvxyv}}vuu~{_^b`^`ff^di`fgddWMVUTNUOUSWSVXWRighghmnlmldofkon[_ZS]YV^_VU_`\W\txtumolounpsqmpo`bgad\f^abcaabe^z}zytu}|yyy~zy|znhmgiccliklijlihzjjmoupmsmnopqqvmsxw~uz{ut}vsyy~|}}}d^`cga\]``^fhhgbQOSPUQXXSUPRXWTOcikjmicjkokoekfiZYZTU_WW[ZUV`[[\ssnrllqrqqwrqsxs\^^f]bc`````]d`isx}wvzrvxwzyyu}bkjdihcjgknfhojm||z|kntkumpqjotvtprtr}wvtxzszwxwy{{~d]\h^bbbaega_dfdRPMMSSUMTKYTRVXSdbckehjlhlgeokjjX]YV^TYZS]XU[]UYrjntuokrvrxroptqb_Za`cZbc_a`bdcjxsrsu{x|yz{x{yyhbmcffekjkmbenjgzy}}}~rqnssqpspuunvvvpt{{xr|sv|{{yvv~z{v}|zc`a\_`]\[ag`_`]^PMTPMRKRPPSTUYUSdlhibbfgicnfmojhVR]X\^[V]W\V`X^Znssmjjjtvmnqrnolfe^[\\f_d_f`]f]e{uszzxs}|{tx}x{jifbhhgjlmnmefok~~{{}}}{pqnlrrkrsvlrqxrvwwwysx{vyyvvx}x}zy}|z~{z]_`]`]ff[[\^egc\QOQLOMTRPWWMXQSObmigfgmjgkemdfooY\\[WXY]S___[VX[ijmqlnrwoplqnuqnaZec_^Z`c`]cgc]guuywtty|t|y}|wvjh`fbcfllceildmj}{~~~{}lligkttkmutsurnqtspttyrv|uu}ut{x}}{y|~]bb]_]]]fb]cdf_]JOUOSTPLORWRRXSTjdichefaccnfflkkXX[]RZS^T\^S]Y\_sihgsjjtjtjqnjoo`b]c^[]e]d]b`ecfrrxswrz{s}x}{}|~cjgkffjnjifjonnmy|x}y|||~impkinouinmjwsvurwsqsoz~}qvtryz{xx}}|Z[YWZc\cZ]e^g_cgLQOLOOIOJROMVVQUa^a``ccfbabgjhhoYS]WQ]QSX[W^[U[Ylnmlgqintntrlmnn_[cYaa_c_`ecgaa_qryopzuyv{s{x{{xdekilffgjfacefnny|y~zyllpmksijqsplqjnqqw{zz{zsttvvu}t}zz|{||}yOLIGNNMQOHITRRPIa^ffggb]efhbjai_PPUVMUTOTVQVRWOVemmejngodffjokqm[`Z_V^YaZU[XV[]Zpnkpswosrrmstorx[[e^egadeh^idfj_u{y|~{yswyz{yy|iiecfclkmqjimhjk}{|~pptroptovnsqonxyuuswxyvx}uy}zz|z{~MIHOPJGGHMRLSHJH]\[\`cbgbdbjb`g`LNRVWOMWYNTTVRSWfhhgnpipjqemhhkpTTR[[`_V]Y]]Y`\Vlmrpolsrywtqnrqwefbg]ccff\_]jfbfxu{xz}ww|w{u{zzkhkoljmfnmfqlhhm~}{}|}}rququpvltsnytppusy~rvv|vu|wyu}x|~KKOENINKORNOKRHM`]d]\_e^fb]gca^bRQMXUTRMRQSVOPPUfefiknikeeokjpqnRR[]ZWV]XZV]Ya\Wkjpommmtlrxspovqce[_baaghi__dhh_u|}ww~uwxs~x}{mfnilnmiddgfmikg}{|{}ussvjvrlwrvosqno{yvztu||w}xuz~|~}||~IHLGMDCINNMNMMHQea\e`__a^\]ba_bbKTQPOKTPSQOVYWQQgchgomemonkinpgp\\[\WZX]ZVa_Y[^Vrqqopikojwnuuowm][fb`_abff]gefhc~ytuw|wyvw~~y}wffcghjglnmnkfgnizz~kmlsqvljvvrqrrluvxt{z}}tvt~|{yy{~~zzz}|~}}EFNMOHENMFHJLMPQ^c`ebbdaa^eacgbgTNOKPRROPRLMQWVPhdlhafgjiflcipfpY[T\W[TZXW[[]V\Zjnpmolssnuomvvpqb_[Zbdc\bdb^a_f`zwtwuxuytyxt~uwuillnbgibmklogflpz~zz|}}|kqmmlrmotujqtvmoqzvxrzwu}t}z~~x~~|~~|~OKNMLJKLMSLNHHLNb^Z_^\\f^gc_^]b^MURNUMVQPRPPWTZPficfekmodfemnmkh\[X_\[V_YUSWZUZ]sjkppmnjvqsjttwo`\[`bd^^b``eegf]ot{vtst}stzw{wy|lanndieimdllhoggz~|~}pvkmujrtvsmtvomxsvyxx{sx{vuw{zv{~~}zy|z}~ECLNOGFFPGGJEHKKd^_^]Z[eg`bcd\f]QOJRQKOPTTRMRKYOfhmkbegfdlcheien]ZYZTUZ_SWV[ZXX]thntkpmpqspwsoqu`]Zb^c^cf``d]`__ru{rsttw}t{|zw}fkdjlcamhgfgkfgdyz|}z~|miskpkmqqmpspxrryu{uvwryr|wwt|vyxz{~{~~z|ENEFEGCMPHBPDEEJ[[^[^^``cbaf_ga]LQNUUNUSWWSUWOSM`ielhfndjflfkdmiR\ZY\UR^WU^U[UT[shilmhtppqoqlkvpa`aa\b]d\_cb^iabs|pysys{x{~vz}}{iahdemkgnehikdkoy}~{{|}}nipjoirrmmpirursrwyutw|}vuxsuyxsv}|}}~z}GFDINBKOBCDHHHMC\`d]`]YdcbZe_abbOJOONQNTLPLPLMRTeeahckccdhfbblgjVSQ[XTVV]^YWYVWWfkrnpqmmqqkookukdcc\[ce\`a`[c`f_nts{y{{wwr{vvzzvjejdffdfilfkhnofz|zx|}|ljrlmshljljlomktp{qurqwsp}us}wt|x~{xz}{}}GHDGIKCLEMLBFNFEW[`^]cbada^e^\_bOMKTKONQRLOVRNTR`h_ebjkabhjhdijdVQSWQ\RWZTZVS^UVorqmmrknrqphunmm_]\[Z]\]`][Zcbc`tvvtyqzz|ruyu}ywbdgfldfgjbflhfel{y~xzy{z{klqigprporuutkmqpxovtwyyurwyrpx{uwz}~~y{y}JLGIKKLOFLFLNKKOYY`Zbd]aa_bc\gfZTSLSPSUKJLTNQKVR`fjha``lejfligeoXQSY\UWYVXV\^US^rqkkolpmhjriptsvY]cd`^Z\XY^`a_[]wsrvrvutp|xx}sw{abjfcjl`ieglckdbz~yw{yx~{|{nonjhhiiqkkprltonvnvvxqwstor|sxt}{wyv}}}{K@IHFHDIGLCFJJKH_Y\V^`^]c]^d`b\ePNQNIQSOMQLKOVWSj_ea_achglckiiehRV[[PXRV\ZYZURR_gjllqjqlppkvjoos^][^b`Xba^af_da_sqtpws{qp|vwvsry`^dbk_jahffiilihuyvwwwz|zymgjoosnjjqhrtkuo~}sr{wurxwvwwwss~x}~{{~{zxv|~yxA?BIIKEFFOGABHMNVZc\_[\Vb[Ya_`cbMIGHQGRTRNQPNUQUhafcahfk`kejglgfPVYRZQYRZXZ\XZ^Qgehgjrkohqqmosto^b]W[^[da[[cYa^]nmosrvsysouvpyu{`i^c_kgcbfblcbel|w{tw|x}}wy{jqflhogmrrklgpoq~~v{tr{ovrtspyuw|rvwvv~zx|y|{FCF?ECGBD@JCDGIK]YVY^_[]`\^W`a_dHMIPGHPGTURNTKQPaa``^_e__bahghhbPPONXTUPV[ZYYUVWlkgjlpjgmplonnjl\YZ`YXY\]\`c_\Ydqrusovrwprvzqy{|feedigadefdacfcgzu{y}x}|x}|{x{noiffpkolpmnknok~~~ljyxyxzmyxrupsuy{zzy~z{x~yx{~|IC>HF@H@AABAGEBDZ\[^^V_Zc^]ZdY_YKQGQJQLNITMOJNINa`_b^`afjijhajffRPQTXZXRPZTPWUXQekeljnhljqqrhqqmU^YY_YbZZ[b]aZ]\onpnqwqtpww{ruzq_fhg``fkgikgaiabtsvu|{w|yxyxlikdkqhoipqrsoqk|~uwuxmwpvvyoqtuupwtuy~||zx|~|@CHJEACDJG?MDDJAUaVYaZ^c_XaYV`ZcKOLLNJMPMMLJOSNWb]g`__``hflffejiOMOTTUVV[RW]QT]SofohkgrqqjqunmpqUa[XXaWZ[c[]^[ZZsnrtqrqxorturrwpfic_efccb_fc`chaxw}x~x{ww}~vwhhlkmkopjolljhru~}~mnsmoutuwoppsww}wxsz{x|}}w~xVSTWXZUUV]Z`[Y^UJFIDNHJBHOIOPMKN_[Yb_aZ_]d`c^hecTSNUVJOQMSPLXRUSjhjkdcjfgjkkkkfjTXV[VUXTTVV]Y_]Trhrjlsopjiotnupobc[Xc\`]b`c`g^_hwsxo|swtx{twwr|xlhkifjgigcchhkek{}y~|}z{kpjqoplkmrkktmplyv|rst|s|qq~{rx{|{~|}UQV[\]WVYZY[WXWWJBLHLKMDDGDFFIGGW\^`]aec\ca\e]d^IPSLQSSUNLWOVLSSgljbbeahkidcjlkjZZTQ\VX\SU_T[U[Tnkrnspkrsiqtukrn]a]]b_dXZg]c_^bgrmz{syzr{wxyvrvuabcjkdambhcfmfon}xwx}y~grlhtousnrqrvlov{roov}tswyzs}xx~yw{~VQVVSXYY^YXUS\W[GGLHEGKJLMJECGIGZ_\[[Z^\Ya^b_Z^\JPNRPQTMQKQMQQSNka`bihfbfhehgmnbT[VXXU\XVS[TTTWUmomhnkqiqusqvmjl]aa_\^eZadZ\b``fqpovqtzyv{w{xxru_fee_fmdfffkgbleyyy{~z||}~ghlqjjnssolnnjvm~vrqruqw||tzvzutq|y{|v}WYWTSZZ[\PYZ[UVVD?DEELKFBALKKPHO]`^_^ZY[_acY]_[hNONTJORRLPRKMRPM``fa`fdcgcfecehgW[QYZSVZZSU[Z\Z`ggnilntqkortokki[[abb^`d_]c^`__aownuwoxuws|r}tys_bfgfckhjmiljlifzw}}w}{xklgnnllkqommqnls~otvxvuqprt|zuywsv~yz|}}|~SYPT\\RVV[WXVZUSD@JGCLIKHJGGKEIBb_\``^X[b[`cd\Z^MTNJMPSJPPQSMNUWadhhgi`mfahhcmhmWZSSWTZ[T^WRZYSRnqpoqopnnmljlqsm]Yc^ZYaa]][d[`a`qvtorno|xuurpyuqg_cdh`kgdlkmhkge{~wv~miioqsrhnokishlt~syutqwtt|yu{s|zrw{z~~|yyzxzyNSSSTVUSPT\TSWYU?FECEBEHDDECCDFAV\]\Y``Z[a``]`[^KPMLUPNTRKTNJIQKiehfieaegegeljkgO[SXXRPZUUTPYT[TggfojngshijtkmsmW\\Y[YX^[Y[^]c^\nssnmtxvopozruvq_febiedfhghbkmhc}yuz|vywzxxnjnpmkmkmgtomtot}otrruurrsrvowvuw~|uz~y}{z{xvzYTVVTRXTRO\S[Z]^GJKBCJLMCCFGGLJJXb``^_[Zd`a`Zfa`LMIRUMJROPLKTQSMbh``f_cebgbkfkmlYPPURWZXUUTSY\YUljihrommirmrsrjj\Z]XZ`^c__bZ`d\]qsvxuzwszptru}pve_^f__gjk`alggecuuzuzw{zyyjohqmohiskjssmsv~z~vwsr{y|zopyyyvzy|wy}zz|{zXTSRPWRX[YXSSQX]GGABKJJJPKHILIDF]XZ\WZ[Y]`_dabYbIRKKRKQJSSRVUIVVg`i_g^feecbiehlbUUOTS[]WVUW[R\][ljflfpqphqooknmrVVbY\`ac`a_ebb]Zltuqllurxqtpso{yc`e`kgbdediaadfdu}xy{}}yzz|ynmophtokjkhhtmkj}|nprpwrxq|xsuyvww~|||z~{}{}~{YXURPNTXXXPZ[RPYKCJEIGKIDHMHKMOH\`W`Z^`\Y]Xbcb__ORRJRNUQJPVUQQXSdhgi_fg`_gecjggaRPSWVXTXSRW\Y[SYmmkigpgjifplijojbbWd`aaa`a\[^]edvnvuuupqvuysq{y{jfkcg`ijfegchhfjwy~}}}{zx~w{zqsrpifppnihlnqnn~xvsnopwvtvpsyyuquz{zx~{{{~|ONOQSRSTYVRWRVXZBJHIBGNMCDDGGGLMYXa^XWYbVZW`_]_^KMMJIJSTPPUJLOSW]gd^bbcikhj`b_gdV[TQ\YYYXYT[]]YXikciifeomkjjlhlm_a[aZYY_cdacd`bdwtqrnssylnvnqsw{ea`hehcfdbejhgcnxtx{~wt{yxylrptnikikwiloqks}|qtrtuyuyxtnvsysr{~y~zz{|~}x{||SPSSUXZQWSX\SVQZHJIFCGMBEIKBDKDEY__Y\WW\`_Z`]X[_MKIPJNVMRMLPLUWRc^^decgcdi_`hcheVQTSRQ\RQT[Z\WU^nemldmhkqhnjohos\ad_Y`ebZ_hc\[]]qkpvmpnuporzwnnxcfh`ieijgekbgjln}t{tv~wxtvzw}|xonqrjkhsqrspoolm{}~rvpsqyoyxw}rx}ruu~~w}|~{{||URYUUUWNQSXSXWQPHNGEGMJDINFPEEGIUZY^`^W`Z]``]`VYKRNNLKNRRKSQOVOW`h``ag^b`e_aib`gW\\WSS[WT\W[WQS]ihhgkjokfkfkfmil]dY`Waa]dba\]]`_vnutssmvtqpsqtow`lgjkejgdckddhnmtrz}xzx}xuvroilpnsjmooqrvrm~zz|~~~ytpstvq{{txtvztty~|~~y~|}}OOXQOPVRRVSXVXTYEADLEDMCIJOLCMMQW[YaZ_ZUX[a^_^\[MMMTSPRMSVPPTMLSe\gae]fg`cbchfb`P\]ZYUSY[XUW]V[Vggmkeljnpenfphpq[\b\[e_a^_b]cdc]rsmuqrltpqtuwvrwfcicaiaeideffefjuy~vx~}wt~v}y}ksmhgtpokqnonlwp~~~zt{{zuvtqq~{rw{wxz~|wzzy}{~RSQMPRSWYNXQPRP[DBGJLFGOJCJMNKIO^[\T^[]TaY`YXZX[PQQPUVSRQWLNOSUM\fb\]__heb]dg^`iSYRUWXY[ZUV[]_^WbdjgeddfhfgnkhiodZ\abcZ][daf`gfatsrrpsvkusruwowvdhieifiicjmcdjijytxvzs|zz{yu|~|ipnjqpiqqqsuwnmp}y|~~|ytvutsuuw~x}zuts{~}~~}}~KSONTVOSPNQPYZXPIFNCGEPDMOHPCLEM_VXT^TZZY_Z\\]V[SPLMJROVVMNPLTXNc]^\ecaZa_\da_dgU]XZWTUX[X^_XV\_kkmknedhloiehnmnd[deZZZde^b]]eabsnpmmlouosuxttnojdehcefadmiecide|rtuxzxwsu~{}u}jmkljouknulmqompy{|zurqtyyuusxzyu{|{{|z|~|RTNOWQSTOTTROVTNKLIDEEIEKDOMOELEZYZVVYRZUYU[W^ZVVPTLOPRVSSLNVNWMd^eg\\^b__g\e_`a\]Z\WY[ZY[TX^^]Vldfikkmkijejjdif`a[bbY_heb^`g_\etkkortoollmpsrpvamkefnjcojcbdjff{zz|syzruvu~|~ytjkknmtlkkrppsqpo|~zz~|}r}vtvzttsvwusq{wz||~|{}}JEA@DIBDBLEIAJFIVQTX\PYVTVUWV[[YNOJKHLQJMKIQIPLK\[VZ\W`b_\Y`aYZ`XPNPSXRQZYSU]R]]ieeg`gjdbbjaidje\``Yaaaca][c]a_agmpnlmhrkskgiqmle]^dgcefifedjclftysppowrwxotztzqemqkgjgrpgelroon}~}{u}||}|}}y~upmymmxuympppzuo~xywvz~z||?BH@?HJFDJFGBJGGROUSUOYXUQTVYOXXPRQOPNPOSMJONVTT]\Z\\`X\]^\aY^_`NUVQ\YVWSQURXVYT]ahadhghcajgbdkeX\U_]`b\Y[_]^Ybfcjnjfhnioirnislmg`_a^^iicgfekf`mtoqoustnoquturzvognpjhlnlmigkmint}t{v}w~qlyqyxzrrqqrovtr|||zwvxyyx~|z~|}BDKDFJJCDIKIFGBERQYSUQZZZTWTRXUWNLKIOMQRRPQLMMLU]][\]X[[[Z[bX`XbWPTPONXQYRZSRVQS`cd__dg]^fhgdefbXX`X\XWa`YcdbZZ_iihgecgihfkligtlbh_^fgahahdcnafhrxqkmnpvxqrosqpokjojmgrloiohntlpz{x~v}~|{vwv|ysussorpnqwrvrvxt}}z{~x}v|~{z{}DAECCGHDBEBGIHEKRPQPQVPPQQ[XVUTUPQPOIJPRTQUMMLRVY]\\YZXYa[^]\`\]SSUX[ZVS]TWXZYSX`ebe_digggfa_`k__WVW^]b`bbcddZY`kijefgdngnhoojor_ihjjgafgfcedchlrklnsrnxxvqyxpsoikqmqqfjkmrmpprmz|uxys{{zvvyvpr{w{xtwxyyswxu}{~{~y|x~}{~w~D@BC?FIIFJCKJGEKMNMUVPWWXTWTTPSUQQKQHNSQOJPPUKMQVYVXT_]Y_XbY`[XZXZQQPZQQ\SQUUUV[[^\chb^dea`i`hf^YY]\Z_Zac]_bdaa^ccjcfokjplkoojljebafbgggldhefgihjtqpkmlrnxxootrrmrrjntomspjikpjnut{vvuz~}wy{z~wrywspspxsqxxqy{tz~xww{|}yyAFKNGJEFKKMLBJLOOSYOTNNTZSUNXV[NRNNMKOROMOONQOVTUX\_]RY[aZ]X`^^VYSYXZVQZSQX_[]\Z\bb_gbh\]c_i^bbib^W^b`dZ[d`\[`agnhbflnfnpelffklk`djfjbfdhakighfcnsosostpjvpuuvnqnkorhopnskqllpmo~}vt}|}uvzu~ssqrzow{ptywuvspy{z{xw|zx|yy|JKDDDKFDJCNMDLDINMOQMRVWSOVLXQNQNKPJSRQNNUMOPLMPWTXUTY_`X[a[WWWcUYYRSYRZXSZZSTVUaYaa^cbcabc^__`^X]\b`adccbcf[fc[kjfhdknpbkohkplri`kdckffjcmmkbhasrouqrtqvnowtunsqphromolmpihnrmqr}r|zy~xx|xu~xsstr{wtsxzr{stst{|}x|~yz}{|xyDEFM@DFDIAEGMDIMQTSROOOTTPSQVTRTQRVLNORONPMRWQMMS_T_US\\WYa[[^]ZVRR[[[VXTYSW\Z[Yecf`]g_]g]i]ghh`Z`\YZ`c_^_\^[`\]gbdflkilnnhikmljbgikf`gkidjjkglcnlpupnkkvqoupqqwmfsgorpkskomoppt|v{y|qr}|zw~}zuutzyyzu{spy}vsu{y{||~vv{|y{x|{DBNCJBFFKLKCEKEJNSPTURSXWSPVUUOQLPRNOQSPOKOOQQRSY\YSVS`[VU`Y\`WaVTWU[UUWY[^Y`XYU^`a]^b`dff`[]ghjZ\cd\d`ZZa^f[^\[jckejmkgolenmjnjgghbaifamjmjgghhvnqsoutmqssuoovnrkrpijnrokjmqmnqzvurzwzvw|z|y}}}tuqw{wt{xs{y}vx{z|}|{~|}x|yv{z|}~~{HEINB?EHJKJJOFPLKVOJTQOQVXPQMVVRJOQMMOOLRMOPLQWVS[ZW[Y]ZYV\Z]V\_VVZZZXQWWZZ[RT\[]`Y\ba``b\`^beddYba`a[ea[f[^e^eiihkigcjggjkkelhidhbadllkjdedgfjgnlopopmslomtrlltiqroqltppontmqlp{sup}{{{v}}szvzy{r|qrrqw{q}xv~tu{~~}}~wxyx~~~{|EFHFJCCGFJLNILHMULQVQTTMLSLOQUMOQRPLPRQNVPOWQQSXWYTOVXVTUTX^__VXSQQVX^TZUWXVXTY_d\]^bg]^aa\^`_`_]_`Z`acb[b_^^_\cilgl`likeilmojjmgglfciimcfmncnlkkmoospqstrkqrrwtgjnjooojrtplnquuxuzzutrxqz|}wt|vxspzu{vw}zv{~ztvyvy|{{~||~}xy{~}IHEEMJHNLKEJKLKIMLQTPMSONWTTQLWQJNRNTVSUTPPSLPUTWTU]VXWT\ZZa\\UZWY[VZRX\\R]WT_`^_Z\\abe_cf\_g^]fYZ^a]^dc[a[g]dbe`fiefikddedkkikogdbdgckglhghihffqlhshrnqsvpksspunrthkppktsussrosstrrt|wx{{xzxr||zxqxxr}vuv}{v|}{}||~{z~{zyz~{|{CHIFOKGNJOLKKNQNPNMRUJSSSTPRLOPPLPUMPRPVNOUWSUWNVS]WUX]TZUR]Y^X]TX[P\TSW][[[^WZXbabad\eZd`]hb]g_d_dbZaZ]_]d^_a\caddg`cl`ggcnjgholaffdfkgkkhfoqdlkkqtmkskisqqkqktssqspiqjpluuwvnvtoyswv{q||{zszu~{x}xr{uvr|vxy|zy{y}yz}}{|}zzz~|{~|z}ILGNEIMFNOLNNHJIPSPMKSNLNNTSRUVVRPLJQQTSMNRSROQQ[VPWZVSQUZV]VUWT]UTWZUVWYV^Y[Y\\`]\_bZZceZ^aae^ZaaZ^\^[e`_^c^acibekf`dhfcfbgfgjkjmfglfjdgldopjdjhgnnkhnjmjuonkuspjrulqmotltvpqstzxqnqwxswtr}yszqyusysuyrz{v}txz~~}x|zz|~~~|~x~x~~FJJINJEKFFFLPGIHPRMIMMPOVOVPRTOMLRTRTPVMLPTTSRYTPZSTPUYZT[S\ZST]\SUV^ZYYU`VU^[X]^ZW\^b^[^e]e\[\c]a`a]\b]afcca_d`eac_`d`k`jkhfhkfdkfmibfdfodemfpgkjqnolspqrskmnpqssrkpluumtrmnvmoronqqytwtyywsyvvsutsxqw|wutvuuv|xwyyyx}{}{z}{{x~}z|GELKJOONJILHMMQKHLJIQLPQTLOKLTSQRTTPVQUMMORWQRWSQ[VYYXPVX^V[[UZ[WUZ\][UVT_WT^[X\^]^`]W`a`Zd]bb^d]_[^\afcf]afh`a^dhgc_fjdkheeaccdbbkdjmheigfhldmjmlqnjhmkknsnrolplsursntvmtmovmrqxtruqvpxtvrtt{zwvuss}x||yutxzz~w|zx~{x{y}}{}~y~~} \ No newline at end of file diff --git a/clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-y.bin b/clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-y.bin new file mode 100644 index 00000000..53a13e47 --- /dev/null +++ b/clients/apple/Tests/PunktfunkKitTests/PyroWaveFixtures/ref-dense444-y.bin @@ -0,0 +1 @@ +0030.171114423759658:99::9<6<577!!! ?>?@:A>>@CA>A>CA$" ""$ # #%&"&!#ACCABAGB?CABHCIB(*)%+'&,-)+(,-'*GDGFHFLJJGMMIIII021+,,-/0+-,,30-ONLLRRQQORPLOTSR1417076383779342PQSSVSUVXTWWSTVS<<:<<=9<:8>9>88<]UXUZ^\\[YZZZXYX@@=@?><@@BC@A??>12551/3362034231666<<<99;868@?=?A?==?@D=?@"$!$!$!#%&&%$&"$FDBAECHBBBFBBFHF,-+&)&'*+*.+,)*(KHMELHFIMNIKIKNJ./2.0,.1-20.0-21MMNNQOMQLPQONOON0350264169335926VWWWXUUSSSUTUTWU:<=:;;9<8=98=<::ZW\XZ\]\\YZ[\^_\AC@>BB@>?A@B@5448214588662593687=8<:9><7>=9;?  !""!$ !@;==B=@BA<=?A=@B#&!%"&&"&'$$&&$"ABFEHFIEGIDFHEII-+((*+/,+++,*.'+HGJJGKHILGKONMOK2.304-1-1/-5../5MPTSOPQQUSRTQTVS4598489573:596::SWYXWXWWYYWU[V[Y8;=8>;:@=?><;@=;\Y\\_]]\]\_a_`]`>BAAC@BCAA?DBBEC2366368756586674! 8;9;8;8:==<=>;<; !# " "# $!>>BE?ACCAACA@?FE)%*'"#$+&+*)))()GFEDFCFDGEHJLJHG,*)+***).-/*.*1.IJNIONJMPOMMLMPR1416244340350245TTSROPRTRVPSVSWW88887:<:4=<7:77:UWXXYYVWWYVX\YZ[;;9=::;;=><>;:=:?>A:!#$%!$ "'&%#!&&D?>>DF?@BEFCABGA%'()*(*,++&'))(+EHGGHFKJHKHHGJJI.,,/+,,+1/22/-22OPNNNPMLJMKMPOOL3//27/1225113668QRQRRRQUPRTRUXQT5779767=89;699:;TUVXZ[Y[Y]ZZWXX\<@A><;=>A@D\\[b[^\^]`aaa]_cFDCDADCAEAEDDDCG943::4;:;:878;:7! >;9@:A9>>=@?@><>$##!$$'#'&$#!"#"@B?BGCFCDDEGGFBC+(%'*&%()+$((())MEGGIFJKJHLJLKKI-,+**1-1+100.31/LJQMPKOQPRQRQQQN3564/20445364649SUUURPVVVTVUXWYX8;<=:;=6=:89;><:W[X[[[\[X\^_[[Z\;?AAAAD>CA?>CDCC__`a^^_ac\ccc``bEACDDGHCBBHFFDEF:755;9:7;;<89>98! "!>=?==<?A@A==@@AD@ACF@``c`a_c``cec`_beHBDCEBEHJGEDEDJI69;989;<>=;=>?<> !" ! !!"# A;A>>@EA??B@@BDA(()"()(%)%&#%%)(HGEAIGIIDIICFHFF-,+,.)*./0).***-KJNLNJJJLNOKPMIM30.3320/3//5122.RPSONPMPQTNRRSTU863:585744;98974VZWUXTZWWWZZZ[YV;<<@><>;??@]`]W][^^^]`Y^^^_@C?BB?BDDEGBDBD@`ab`c^_becbbbbddFEHGJGKHHGHJGHKI:>>;8=;=;;9<9:?:#! # """&" @A=>CDC@ABB=?ACG('#'#&(%$&+%%+(&CJFGFFJFFKIKJJIH.*),0-.0+0.0---,MJOJLLPNQMLOLQPQ3/2021/311520566OSOQQTURRQTTRTVW:6524:7;59567::;[TU\YWX\\TZY[Z]X@=9@?=;A=?:=?==A]]_^[\\^^^`b`a_aF?BDB@FEAADBGBBCcedcfb`deehfccdbEFHFHFJHJHGKHIHG=;7:>=@>;>>>A>=? #%#$#$!% !!>@?C=@@BCCBBFBGE%&'&'&+')&'(*++%CFEGIJHHFJKKLLLE++-.+++/..-/00,,LNKPLNKMRMNQLMMM1.56200076511056VUNRVTPRVTSTWWWX;5<85498;96<7=8:;>>>BB>=;:@@==AA;A?=<$##"%"$#!&'!%%(??DDEEBECFGGCEAD*)+%+%*','&,-)+)LKLGELIMJIMJKLNH.+*-,1/00/1--/-/RPOQQLRPQNSLTOTO6042836537868393RVTQSVWVTTSRUVUW8:7:9:7>>:?>?;8@XW^^W\Z\]Z[]_Y][;??CBC?@?a_`_a`]_``c]_aa_@FIBCEEDHGFEEJGJccaacdeddgeccegfMMLHJIKKJLIKMMLL@A>;BA??BC?@CCB@$#'#%$% $#&&'"("CACDECEEDCEIGIBE)-&)(')*-.(-*+-,FMIJMHKMHMKJJIHJ21-..../.-0001.4PNSMRMRPPOSOTSMS6463393444245549\Y\\Y^[Z^[[[][_]>>=B>?>@CA@BBBCD_aac`aaa_abbcdecDGGEHFCIDEGEFGFHeffehghefihhhihgKLNMONLLMNKMLMNM?B@C>@B@@B@E@A??%"%&)&'(()*&*(%+GDBCFCIFFEGLKDIG'(-*..*+(0*0//*/HJNKIHIOPKMLKLKM030.1/342/244652RSNOONTSSRUOQOQQ6767:79647994844YWZYUVZXXXUX[]UZ<=<=@;:=@=A@AB??[ZZZY\Y`[]]\[\^]D@B??DEDAEAFECAG_fbe_bec`dbfbaaaCFGEGDFHIIIHGGJKjjjgighfijihgiilOMNKMNNLMNNRNOPO=?B@DE@@BEAFDCCD&)+($,+$$'%('),(DHJIFFHJGKJGMHLL*(0-+-///*+/-/-1PNNNMLLNMPKMOLMP/1.201431/253351PPRTTUUWURURSWSW49:;;6=985898;9?YYY[WWY^VXXYWW\^>=;=@<:A=@@^^][a_]\abbabaaaGDGEFGAFDEHGCHFCgghaddgebgggebcdHJIIKGKOINHMGIHMfijlimlkjkniikljMLOPSLNOQMQORNPQAEAF@CBIHGB@AGIA*,(,+&-('')(),)-GMKJJLLMFJIKIIJM0/-/-./.+3,0/-2/NPLNQPSPQNLPSTTR2522655546652288SRWQVSSTVRUVVUWZ;6<:<9=;;<9<;>:;Y\]XX]X[]^\\X[]_A@@>@AB@=>CDDC>Bb`d``a]c`ccaacc_BFCFHAEHJFDFDDDFbhgeddhecgjhghgcMILGOJMHIKLOPONPhiikimjonjhoinkiSOMNRORRRQTRSQRS)&*%&$($*(''*,+-KDFEDHLEFKJKJJIL)-.-/.1/.+-0/,1/PMNPNNLOLPNONKPP5702614176443462TPTUSPQVVVRTVVSV66;:97<688<<7<89UWYVWZWVXVW[W\Z^?<>>?><=9<\]\ZY[[]W^Z[[[Z^>=>A<>BB=<>@D>CF\^`bdb^aecc^^`e^FFFFEFDFECJFHFDHdheiighfgffieiilNHLIJKOLMOPOMNKMnknniijlnlplnnpoPRSPNRPOQPSNTNQStqnospqoppqrsqqq)*(.'((-'.--**-+JIGKLNLLKKKLIKON1004,,-00/-/04/1OLOLLPRPMSRPSUTN6583435476674:89UXTVQXRRYXTU[SWV=:9=9;>>:99;<>?>XXW[[Y[[^X_\`]_`B?C>D>>A=?D@?C@Aa^]b`b`^b^dafcbeDGGHGCEFDIKDIIDKbiadhejhjiggfkhiIMNKPLJKOMHKJOKOlkmnimljjqkjkkpmTTONPUPSQQRUTTRTsststrtooqstssrq&)+)))(,)*,,*/--LNMLJIHKKJMNLNPO0.0/40.0101235/1PNNTNPOQPTORPUUU6497876689888<83XVVXZTVYWVVUUVVY==;=8@9EEBC??BCEFCEECG^`bd`ae`dbg`cbcdIDJEJJEGIELJJIGLdefiighfijjgglnkKJLJKKLKPPQPQQORpopkqlpkmrpootnrNRQPRPUWVPSRPUWTtrqrurtsssqtuvuu**+,**)++0)-1,+*JLMLKJKNLLQOMPQR302312443/125612PRTWUTOTSUPPVUQW74:98;9:9;768=<=ZUYVYYZU[YZ]]U]\9===<;@;??@@A@@@^]]_][^^[Z\]^_\^A?CB@BEA@DAAHGHE`acfd`faffhcfhhbFIKJIFHJMIKGNIKFlekjfhjfgijimlnhQMMNLNRNPNRNTMMNlmokmsspoppnlnnrSTSSWWWWTXVVTWSXptvusqtvtvsusuuu'*...+.-.*-040/2MPNMNNMKQPOKLOPL3124634232248424UQRTWQQUUSTWRTST6<9:9996:<9;=::9V[ZWXXZY]^^W\^VZ>?>>@<;A:]^b]b_ca^^a`a^cbDGDB@GDDGCDFCIHBhfh`hehfghgcdhifIJJIKLNMLOHKOLKIkfmijokkmmjlijloQOMPOMQOSNPTQPSNsqnlmmqtssorqtuoSUUWXZRRUYWUTYWVxwsstuvuruwusuvx,++,1+1021111//,NPLLPQLOMQPMQRQR/367847587338375UPSQSVSWXSXVUVUR899<=99=788\W\XZZY\__Y\]]YY=@B>>@AA@>AD=b`ca_c_acbdaced`AAIGGGGCBDFEHDDCgdgiefdecijheiigHMNIIIMMOJNPNMKLgioiojokilnjnookSQMQTOSPSPTRVTRToqmrptntpuqsoqttWXTWWWVUZZUUY[UXxxuvvvsswtwsuvvy0-+-/3/13111/-13RMQOPPNONOOMPUMT11668635333:87:5XSQUVWTVRSVXZTYT:==9:::<::<==;?>9:>;@?@@A?@><<==?@?AA><=\_^_^a__]^]b\_]_ABABABFBBCGFCEEEddd`ababfhegdgceHJEFIFFKHLMKNINIgjjkjkmjhjmljlikOQOQKSRMOLLNMQPSnnlmmnpqrprqorqpRRUTXYTTSWURVTWWuqqwrqyvtyxsytttW[Y^ZYWX][[XZZ^]wxyyzzxz}|~}z{}{1355466777588663QTPRUWSRRRSYUTWS:::;87877<;?=;9;?BC=BCDBAC]a_a^b_aabd_be`aFGFDFBGEEGFFGIFDegegcdibdidfghfhJLIHMGNKNNJNMLIMigijnmlknkmjhplnPNMNSPNTNRSNUQOPmmpopottspststssWSRUVZZXWWRUTSUYxsxxvtuvzvtuvuz|[_X^Z[Y_[[`[_\^`xyxz|~}|~z|{||6518477785565554UTSTRTTXXWVVXUVZ;98;=7>=<=8;:=>@\YWY^YX[]\]Z\^^]@@CCA<@A@>?AB?>@^`aa]b^babda`baaDFEDBIECCGGGKBGEfgfdchjdgcfgggggJIOMKLOILNNLJJPJkhmikkmjjjppkmjmNPQQPQVNURTUPUSUnnpqosooouoqqvqs[WVWTVXUTWZXWVVXuuwywvtzuvtw{x{|_YZ]Y[Z\^Z^^\`\_{~~~~}||{}}}4743489653765976XRSVSUYZVUUS[X\V=>>=??;=9=9??>:;[\]Z`\YX^[]Z]`]bB@>=B?DC@CBB@@CCb^a`_e_db_`bbabbFGFHEDIHIKHFIKIJhffdekhfkhdeegmkJMLOKPJQOPQPRNQPljpmomnpqlkqppppOPPTTRSOQVRTRWPUoqpsqptsutttvrutZVTWWXY[WVXW[ZYXuwuwyyxyx}{yxx~x[Z]``^[ZbZ]b``^^|}~~}}|~~4:3363:;68;969;=<8=::;<><@@AC?__]`]a`^]Z][_]\dDDA@D=@CEEDAGBECd`cdg_dd`hcc`chgEEGJHGHFIIJJGJIFigkjkffkfjlgnlolPIQOMQLPORORLLLQolkmnmmkkmnqqqsuPPQRQPQTTXWQUTTTvruuqrsxquwvwryx[\WVWZ\VX[]WWY^`uzyz}}}x}|}~|y|Za^]__bbbabbaccb~~}~<644;:;666676>8<[\XZZXZZ[]Y]Z^WY==?;B;=<>??@@>CB^`_\\ccb^\`^b_a`AFFCFBGDCCEHBHCEfdeccbhecafffeceLIIMLKHHMGHNMOJHlhigfihmgkhhkjinLPLTLRQQOTPONSNOopnpmmnnqsmouqntWTSRTRSQWVTZRZXTtxrttsstuvuw{t{tX]ZY][X^Z_]Y[ZaZv}~z{yy{}x{{~{]``]c^_b_cc^`bab:86;6:787<>8;6;<@B=@BC?AAD=?]a`d\a`_a`^\`abcBCAGECBHBDFJBDBKbfecbidbbfaeidfeEGMGKGHIMIIKOMMQlfljllnijnjmljloPPRLQSRQROPNOONRnsstsonounqnpponTUTXVRYUTVXWYT[Wrvwtrvyzyzwuwvwx[YYX][]Y`^Y`Z^Zb{}~xz{||}||~|c^c]c_^dbfb^`aba~VUSXYTUYZYY\[[YW9=<?BZ^Z^`]^a`b[`ab\cCDCCDEC?EGEDDFGI_efbedaacdcgabafGJFGJIHHMFHJKNNHkiekigmkiloimjhlNPNMOKNLMPNLRSOQnnqsromlprqmqpptRUVTUTTSSXRSTUWUpwwtwwvvvwtvsssvXXZWWZ\ZX]]XXYYZyw}yyw{ywy{}}|{}a^c^\^]_`^`^dc^^~}|~}~~ffgcfffdfhcghfgd\U]VYXVZW]WZ[\\]BB<<@@=>BA@>B@C@`b]abbbbaa^abaabCEAHACDBCFHIFGFE`ibeeggcgcffegkcJIJLMMMHFFJKLKJPjkjjignlkllimlmnNOPONULOQRONSTSQlplrnpsqqpqquqptWVSTUSTVY[WXUWXXvvrzsuwvyxww{wxxZ]Z_\_[[Z]\\]\Y_~zyz}}|{}~}z|}~_`c_`a`acceba``e~ghgfhgeghgeffgigXXXZY[W^\YZYZ]\Z@B?>ACC=CCDAEDDE`b]_^__`abcee_f`CGBDGDDIJFDHDEDCeifieehhcgedhfhkLGMMHHMNNNNMOLMNkmnlnlpmmmmkjlolMOTRMQRTQQRRUPOStqopuqpstsurpqqwSRUUSUWWWVUZWZZYxvvw|wwuzz|uyw|w]`ZY[_[]^_^^_``bw}}~}|z|~|}||cfb_bdeffb`dcbfb~ghfhjjghffjjhjii_]^]\^][]`Z`^^\Z=>?@CDA?CDECDDDDbcbbcba]eef_`dabEHEGIIGDDDFHKJHFhidjkjggeeeehgijJLJJNMNMMNPNKLMPkiiimpnmnlnnomkoQSPPNRRSTSSSSRUUvrpursqutqttttqvX[UX[U[X[Y[ZWY[]tu{zzx|y{zu|vvwZ^^Za[][^``b]\^b{{}~~~}zz~a_daefbgadefdcgeeedfeggigikhjkijXY^_`^[_\[`]`ab`>=?@@C?DECBBDDCCceea`a`c`ccgbcadCFHILKHEKKJFKJIFekiiijifefmlffikKIQINNOKKLPOJNLQnlmklrjnrlklrpmrOTPVWTQQUTUVTTVStqssvwqvsruwxwrqXV\XX\\WZVYX[Z\Y|wyz{y|wx~y|~}|}_\_`]^b\]_b^d^]b~}}~|}fdahdhfggfbbeceghffjijijhmmghjll[^^`]]\_\b^`]]]aCB?DC@FDCBCDCHHDaecgffefghdecceiKDLLFGKJKLLIJMNKekjlkififoklhlijMPJPJLNQQONOSLPOnmrrqjpomqqmoorsPVWWVUUUVTTYYZUUvrttvwqttvvuswwvVUVY\]\]][\Z\[Y[zz{{{|}|{}||}\db^`_b^^^b`e`bd}}}~~gggigfgjbefeefielknlkjkjklijkkll]b]a^`^a`]^d`__cACAGADHDFDAEFJIGei`igfiddfdfhfjjIILINJNPLLNMIKLPjojjhhoiliokiiolPNRRNPQTMPSORTRPrmnqpnqrotopvqqqRTXWYWXXVUTWV[UXwtvrswuvzzvyxywyX\Z][YZ_[\[\_`Z`z~|{{~zx|z}}~d]^cb^`ab_a`d_`aeegeeieeghijjfeglkmjlkojljjomklkbd^`]^a`_`^bc`dbHHFFEDFFKDJGDKEDdjgefkfhcfkhhhleOLKJMKINMLJLLLMOjilkkooiqponlmlsTMUVSQOTQQRTUWSUtqmssnqqrtussxqsTUTWXUUWXXWVX[Z[uwwwv|x{xx{|x{xyYa_Z_\`^^]]_aa][}}~~~}}|~{|a`ab`d`ef`cgbcdaieifeimkhighhiggmkllompnqnnrpoqp`__`c`b`adabfaffCEGDEEFGILGILKJGfgdgdejfidgfhhfmIMOMILILKOPPOOQQimllpknllonnmqomPQPRSROUTSRVQUPTotrvtopptpvuwtuvWZW[WUXYZ[ZVZY[\v|xxt{yy|v{{z~{zZ_Z^_\`\ca_ccb`c||}|~edbcebahhaeechgblekkjilkilgfhmkhqljloonoqpqpmmpngdffabefdb``ehdcEGKCIKFKIHHIKIGIijeefgkhijlfjjlfMNPLJLNQLTPPNONNqlnpllqmjsonkrltPSSTTSRTRTVWSVQXwupswvruwrwusrxuYYX[VVYXYXZZ_\][u|xyxyw{~y||{}~}\^\^abaada``aabc~~~~}gbgdbehifjibicgfghhmghkjkmijikmoonnrqronnqrpnopue`gahifiechdfdedIGGHIHNINHMKLKJJflikliiiilhnhhiiNMRPTMOSROQOMQNUopnmqoqnpnpqurtpVVVUUTVURUWWZYTTtuxuwxrwyuwyzswt]ZY^\[ZY\YZ[^Z\\{~xy{yx|zz}|}~^`a_ac^d`^a`ebbc~bfhfcehfdhjkefjgkhmnonjhklkooklltrpspurqqtqpqttsebfbdefhefifhgffIIKMLJKMNMJKMIJPnmhklkinpniomommMMOQRNNUPPOPRRPSooqpposuomoossssUTUVSYSUXR\ZWWXWrswtuytyzvxywwxu\\\\[]]]][]]`^^\y||z|zz~}{{yaaba_acbecfb`ecchdjiiljjihijkmhgjkkllnmlnololnoootrrottsssrtwutsddegfdceggefkjhhGILOIJJOLJPMNJLQljlnklioojkmkonsSSQTOPPNTVQQUSRRonqpnntruppquvrvVUWZUUZYXWW[YVYYtrtvy{uvxv{{y|y{^^ZZ^a__\^`^_`__}~{}}~{~{{~`aaeb__fcaed`hbbfkkhfkihihmkmklekoorprpnnpolstloptopsuursrtuurvwffdgjclhfhihfgmhPOKKOOOQQKJNMOPOlqjnopqkposqlqrqUQQQVUTSUSVQRUUSttqrtuvptqtvrtwqVWZ\YZ[[YY\\Y]W_yvtv|yu}yw|w{{{y``_[_`_a\]__^a^_~{{|}~}}acaeeggfbbfhebjcikjhgngkfhjhnlhmlnpmopnnrroprooprstuwwuvxxuusxsteiijjggjlihmlhjhPRJNJNQNRRTNQRMOppllmnqqlnmnmrruVRWPVSSWYQXRRVVTsxrrtwvrysrxrswvTXYZXYWZWVXY^Y[Z{{zx|y|x}y}v}yy_]^\a^^b_aceae_b}~|~bhhdchhccdfjidggkliloihhlnimikilokorpttoqrptovvvvswtruwwuyuwxvuukgmmjnkjlnilknooRKNRSROQONOPRSPSqpqmsrqrrpttoopsWSVTXPZXZRSUXZRYwwztyyyvxwvxwyyvX[^^\\XZZZZW[Z`Z{}}|{y~{{|~|~|zybbbaa`ba`cdd`cafjfeccghgefhiiejlokhkjjmlkmnnnpmrnrnvrtrtppqqwtuwszxyyxtvxwvwyyxyPOKNKJRNQLSNLNPSpnllmnnlpqrtnsntWQVVPRSSSXUYURYWwtswvvxqtsruvuyt\YXZWXZ\Y]\WZXXZ|}{xw{|{y{zz~}|_^^ca\]^_cbc_ada}~|~}bbeceeddceggddddlglhigjhlnonininonpqqusprvtotnrprvywzvsyvzxuywxvNMNONPOMOQULROOPmkllrsrtnqprrpslSWSRPUWVSVTVVTUUwwutstwwxyz{yxzwW^W\X[XYZZ[Y]\ZY{vxwvz~~|~~{yxy}[]ac`bdaaa`^ae`c|}dbdddhkhfdehgfgkjjjklijkonlmppjlroopprppsrqsuvpsvxxvxutuuwwuyzyxSQROLSNOOTOOSQSTmmqlrstnpuspoupqWYUSTVVYXYYVY[UXxyusvwxztuyzz{|{YWY^Y^XZa]][\\[\|~w{zz}~|z}^_bb`a``fc`b_d`ehdfieghhjgfiifnhmoillkmlmnkkpnlptpprorqsuqryutwszzxwxx|wvwxwxzx{RQTTOSSRPNQRQQUUqpqsoqpqqttstrwtZXTXZ[[WYZ\UWVYY{uwwyxvwvyzz}w|~^\\]]Y^[Z[`]\aa^y~z~||}{}e_ebbebbeffdceefjhggggjjnmklfkhhnljlnmrlplqomosntpqsqsqvxurqvvwsu{{{|y{|}zz{z~||VROVRPTUUVSVQQTUtrrptuqutrsuuwvrXUUXVTVZXWXVZ][Xz}y{vwwvy|yy|y|^\][```cb`^]^bab}}}||}~acc`bfcdeiiefafdmnhfkikjmmiligpmnmsrsormstosqnoswqqvuwuxwytwvyzuz}yy|z|{z~{OOQQSQSTSRYVRYWUstvsrrsursrwyyyvZXX[[YYXVY^VZ[^[y{zvzxy~x|yzzyy}a_[c^]]]ba]`]aac|}~{~~hcaciidcfcfedfjihlfogjnmjjjlmjomppqrmnrppopqrrunvrssxvsssvvuvwvyx{~|~|y}y~}SSRWTTRTTYZTXXYXvvuttryyvysxzxyx]YXY[XZX[Z]]YZ`_yyx}|{}~}|y~~z}ab^__be^a`]fdccf}}cbeghjjdcffigkhgimilkkjlilmlokloottnrqpurpuqusuwuttzwwzy{{{uwwx}}|~z|z|{{|}|RTWWWWYXTTUZVYUYwwtwyvzt{wzwvx|xY[][[`Y_[_ZYZ[]]|z{{yy}||{}~acc_ddaadcaegcdf~fgfgejfkfkfjiifimppqnqnknpporqqquosqrsrvsruwqvswvx{{wuzw|yxy~zz{~~||}YXZXYUYYYXYXV]Z]wyxz{wvy{{yz~|yx[[Y[`[_\^[^]cb_]y}|{{}__bfadadabdadbhfijfiifijlimnnmmnpopmjrpjproqstqpwspsturtustuyrtyywwy|z~w}{~|}y~z~~~UVZXXUV[[YZXZZW[|}{y{yyyx~xxy{zyZ^`_`_b]_]b^^^b_}~~~}~aa`baedahcbchdffhefjnjgikijlnmlnnmmjlpnpskopnrqnrsyuquyxtyrsxtuv~v}{}y}~z~zy}|}~XXWXZXU\ZWZV]YZ[{}yvz|}yww~zx~~~^_]_`aa\b_cbb^dc~||~bedcbebefdfeggiflhnlmnlllkilmmljoqrntrqumqpusurvwsvuxwxxxxvtywuvx||}xzz|z}}}~~XZY\ZYZ]Y[^[Y[Z_~}{z|}}{y~~{cdc_dac`eddgaaec|~}~eecbfgiecdhgjilhkpnnmniojkkooqmrrqowoqvprpqqrrur{zyxuvuwyzv{uz{y{z|{~{~~~~~}~X\Y`^\^]Y[\^[Z]ax~y~~z~~~||}a`adebfa`de``bchghgeicehmjfflkmilmmmmpomllnolompuspwvqqvvsurxsvqvywzvzvxz{xxz}}z~|}}}[`^`]\[]_a[_b]b`{~||~}~~eaddcaafacaichgaghghlkmjjknfnkkikqpnoolllprpopmrtutussvvuuwyrtwu||y|}{x{{}||{{}~~~Zaba_a]^b^a`bc_b}}}~gagfeggcbbdfdiieiljjgkkihjnoloolssmlponrsupostrsqrqtxvtwwvss{{sz|zxz~y~|}~{~zb]a``^b`_\]b]_ca~}~~eicebjffekiifefffiljhmnnnmohplkqknsqqtsqosvttttrxywtux{yxzyuuy}x|{~z}z~~}}dbacafhbcbbghghdgghjnkjmlnolholomslpnnnnmrnosnrtwusswwvxvttwztuvwx|w|{~y~x}}}}~|~}~dibdcehdcffkegkigjjknhlmnlmpnjioqomspppmtrnnprrouvtsuzzvtyvtvtxt{|y}|~{|y}|}~||gbgfgefhehcjdehkiomihllnojjojpnloqopqsruprvurqutwswutz{vzzw{z{|w}}{|}||~{~|{gfjildljejgjjgflkmmnpqknmmnpomsorssswuwqtruxvrvwyu{tvyz||xxyyz{}~}}~dhkjlmjkimjgmlkmklmmmokqnpnoprrotuvxrwsurvryxryt|w|xvw||}|xxxz}~}~}}~jkghgifiglkhhloopoksmoosstqpurpovywtwttxtuswwyuwz~{{~~yz~{|}y||lnimilhnmojopolnrtprposqopntqtvnvstsvwsztuuvxxyv|{y{~zz{}{}mkinnnmnkolkjmnlpqrrpvoqrqstsvttuxt{{uu{wwzz|y{|}xy}}||~}milnpklmlqqoopqptqtttuqrtqwuvxsxtwuxy}yx}||yw{{{|~~~~nnrnmokprrrtsrsnpxprqwwuywyysxyywxy{yx|y{|}~{~~{}~~~~~qnpmqmssroqtpotpsuvyuxxszvttyuuvx{x~~~~{}z{z{~pmoruporuuvpurppxwwrxvysyuzx|wxwy||z{|{{~z}upquuuuusutssuquzwv|xu|v{|yx}wy{~}~{z|}}|}soptsursrvyxxwtrzww~}{}xz|xvzy}}~}~~uruvswswtvxxwuvw~|{~yyzw}zz}}~~tvvwruxuxvtuuyu|yy~xzyz{}{z}~wwsrpxrquxuxxwvtvxyx{|y{x~||}|}{}}}~~wvruywsvszysuvyvxyz{|{{y|z}{|~~~xyuuvs{usyx|wx{x~y||~}|{{}}uyyxtvz{xzv{{|zz}z|{~}{~vxz}v{v|x}z}{}z}~~}|{}|}þĿzvyw|z~x{w|{||}~ġ¿~z~z~|y|z|{~~{{}|z}|~~~¿šŀ~~{{~~}ĽĿ~}~}}¿Ƀ~~ƿƧ˄¾Ŀìʄ¿ħíς¿ĿŮ˄¾ƤͰυªϭΧǧɮѳĿƪ̯Ӵ¾ħˬԶ¿ɧϯӸž¾ŤȭҳӺľſ̫̱׺¥ͭѴ׺¾½ɦΫηּÿľ¿Ƭѳֵ׼¥˩ʹָٺ¤Ŀ©ƬϳӹݺáĨ˪ұټܾý¾±¾ĽƦϰձռõ¦ʬαжܻ¹¸ÿǩ̭Թ׻»½½ýÿ´¾áªȮαٶ޿ĽřžŨŮҲշ׽䛙ÿĨǭѲٺ߽û睚ëȮձշ¼ý矟ţŦѫгԾ߽ýĿĿ螡¾˨ʱԵؿſƿ睠¿Ư˰Ҵؿ½ꤡľĥƬβӶ׿쥢ΰѴѶټ¾ž먧ë˰η׾ܾĿ좢ǩͭζ駦ſ˳ӻӽ¼驨ȿª̳ѷ½맧ſǮʶι¿몫dzȲ͸ľ먭ƿƴǹӿ¾뭮ĿǾƺľ÷ѿԿĿؽ½˹˹¾տپÿÿ˻˽¿ܿõ˹ͽ¾žݿÿIJǹϽſĿݽľƴ̺ξǾþžĿöżĿľƾĹȻ½üſ½¿ùÿ¿Žĸ˿Ŀþ½¿ƿ¼ÿĿĿ¿¿Ŀýÿ \ No newline at end of file diff --git a/docs-site/content/docs/pyrowave.md b/docs-site/content/docs/pyrowave.md index 4299eff4..b1cadca9 100644 --- a/docs-site/content/docs/pyrowave.md +++ b/docs-site/content/docs/pyrowave.md @@ -36,11 +36,14 @@ Bandwidth. At the codec's ~1.6 bits-per-pixel operating point (4:2:0, 60 fps): | 2560×1440 @ 60 | ≈ 355 Mbps | | 3840×2160 @ 60 | ≈ 800 Mbps | -120 Hz doubles these. Gigabit Ethernet tops out around 940 Mbps of payload, so 4K60 wants -2.5GbE (or a lower rate). **Do not run this over Wi-Fi** — that's what HEVC/AV1 are for. +120 Hz doubles these, 4:4:4 multiplies them by ~1.6, and an HDR (10-bit) session adds ~15 %. +Gigabit Ethernet tops out around 940 Mbps of payload, so 4K60 wants 2.5GbE (or a lower +rate). **Do not run this over Wi-Fi** — that's what HEVC/AV1 are for. -Also: PyroWave is **8-bit SDR only**. An HDR session stays on HEVC/AV1 regardless of this -setting. +PyroWave follows the same 4:4:4 and HDR settings as HEVC/AV1: a session negotiates +full-chroma 4:4:4 when your client's 4:4:4 setting is on, and HDR (BT.2020 PQ, carried in +16-bit planes) when the host's display pipeline is HDR — currently the Windows host only +(the Linux host's capture path has no HDR source yet, so Linux-hosted sessions are SDR). ## Turning it on @@ -53,10 +56,10 @@ setting. gamepad console, or launch with `PUNKTFUNK_PREFER_PYROWAVE=1`. - Apple (Mac, Apple TV 4K, iPad — wired networking strongly recommended): set **Settings → Codec → PyroWave (wired LAN)**. The option appears only on devices whose - GPU passes the decode probe (Apple Silicon and A13-class or newer); picking it forces - the session SDR. + GPU passes the decode probe (Apple Silicon and A13-class or newer). The decoder follows + the stream: 4:2:0 or 4:4:4, SDR or HDR, per what the session negotiated. 3. Leave the bitrate on Automatic: a PyroWave session pins itself to the ~1.6 bpp rate for - your mode (≈200 Mbps at 1080p60). An explicit bitrate is honored if you set one, but the + your mode (≈200 Mbps at 1080p60; ~2.6 bpp for 4:4:4, +15 % for HDR). An explicit bitrate is honored if you set one, but the adaptive-bitrate controller stays off either way — this codec has no useful low-rate regime, so under sustained loss the right move is switching back to HEVC, not degrading. The pin follows the resolution: a mid-stream resize (e.g. Match window) re-pins the rate @@ -66,7 +69,6 @@ The stats overlay shows `pyrowave` as the decode path when the mode is active. ## Current limits -- Linux host + Linux client (including docked Deck) and Apple clients (native Metal decode - on Mac / Apple TV 4K / iPad) today; the Windows host is tracked on the - [roadmap](/docs/roadmap). -- 8-bit SDR, 4:2:0 only. +- Linux and Windows hosts; Linux clients (including docked Deck) and Apple clients (native + Metal decode on Mac / Apple TV 4K / iPad) today. +- HDR needs a Windows host (the Linux host's capture path has no HDR source yet).