mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-16 16:21:30 +02:00
fix(switch): widen Pikachu PCM to 16-bit stereo without Source channel probe
Source:getChannelCount could skip the #626 widen on love-nx, and keeping 8-bit depth into a stereo buffer still sounded wrong on audren. Decode the file via newSoundData, always emit 16-bit stereo like ChipSynth, and write fresh pika-cry WAVs as stereo at extract time so re-imports skip the hop. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2023,21 +2023,23 @@ end
|
||||
-- PikachuCriesPointerTable, 42 `dba` rows; each clip is `dw length` then
|
||||
-- 1-bit PCM, MSB first -- home/pikachu_cries.asm PlayPikachuPCM toggles
|
||||
-- rAUD3LEVEL per bit at roughly 190 CPU cycles a sample). Decoded to
|
||||
-- plain 8-bit mono WAVs; returns the clip count for data.audio.pikaCries,
|
||||
-- 16-bit stereo WAVs (identical L/R) so OpenAL never spatializes them as
|
||||
-- ambient surround (#626); returns the clip count for data.audio.pikaCries,
|
||||
-- or nil when the manifest has no pointer table (Red/Blue).
|
||||
function RomExtractor:extractPikachuCries()
|
||||
if not self.symbols["PikachuCriesPointerTable"] then return nil end
|
||||
local NUM = 42 -- NUM_PIKA_CRIES
|
||||
local RATE = 22050 -- ~4.19 MHz / ~190 cycles per sample
|
||||
-- byte -> 8 samples, MSB first (LoadNextSoundClipSample: `and $80`)
|
||||
-- byte -> 8 mono sample levels, MSB first (LoadNextSoundClipSample: `and $80`)
|
||||
-- levels match the old unsigned-8 WAV (on=0xE0, off=0x20) as floats in [-1,1]
|
||||
local lut = {}
|
||||
for byte = 0, 255 do
|
||||
local out = {}
|
||||
for bit = 7, 0, -1 do
|
||||
local on = math.floor(byte / 2 ^ bit) % 2 == 1
|
||||
out[#out + 1] = string.char(on and 0xE0 or 0x20)
|
||||
out[#out + 1] = on and ((0xE0 - 128) / 128) or ((0x20 - 128) / 128)
|
||||
end
|
||||
lut[byte] = table.concat(out)
|
||||
lut[byte] = out
|
||||
end
|
||||
local function u16(v)
|
||||
return string.char(v % 256, math.floor(v / 256) % 256)
|
||||
@@ -2046,6 +2048,12 @@ function RomExtractor:extractPikachuCries()
|
||||
return string.char(v % 256, math.floor(v / 256) % 256,
|
||||
math.floor(v / 65536) % 256, math.floor(v / 16777216) % 256)
|
||||
end
|
||||
local function i16le(f)
|
||||
local v = math.floor(f * 32767 + (f >= 0 and 0.5 or -0.5))
|
||||
if v > 32767 then v = 32767 elseif v < -32768 then v = -32768 end
|
||||
if v < 0 then v = v + 65536 end
|
||||
return string.char(v % 256, math.floor(v / 256) % 256)
|
||||
end
|
||||
local CacheFs = require("src.import.CacheFs")
|
||||
local pointers = self:symbol("PikachuCriesPointerTable")
|
||||
for index = 0, NUM - 1 do
|
||||
@@ -2054,11 +2062,16 @@ function RomExtractor:extractPikachuCries()
|
||||
local header = self.rom:bytes(bank, address, 2)
|
||||
local length = header[1] + header[2] * 256
|
||||
local raw = self.rom:bytes(bank, address + 2, length)
|
||||
local samples = {}
|
||||
for i, byte in ipairs(raw) do samples[i] = lut[byte] end
|
||||
local pcm = table.concat(samples)
|
||||
local parts = {}
|
||||
for _, byte in ipairs(raw) do
|
||||
for _, level in ipairs(lut[byte]) do
|
||||
local s = i16le(level)
|
||||
parts[#parts + 1] = s .. s -- identical L/R (#626)
|
||||
end
|
||||
end
|
||||
local pcm = table.concat(parts)
|
||||
local wav = "RIFF" .. u32(36 + #pcm) .. "WAVEfmt " .. u32(16)
|
||||
.. u16(1) .. u16(1) .. u32(RATE) .. u32(RATE) .. u16(1) .. u16(8)
|
||||
.. u16(1) .. u16(2) .. u32(RATE) .. u32(RATE * 4) .. u16(4) .. u16(16)
|
||||
.. "data" .. u32(#pcm) .. pcm
|
||||
local ok, err = CacheFs.write(
|
||||
("assets/generated/audio/pika_cries/cry_%02d.wav"):format(index + 1),
|
||||
|
||||
Reference in New Issue
Block a user