Add import options for bit depth and sample rate

This commit is contained in:
Haoyu Qiu 2023-01-04 17:44:46 +08:00
parent 5b910afb64
commit 576708bb4a
6 changed files with 64 additions and 17 deletions

View File

@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Bit depth and sample rate import options.
- Paste from JSXFR.
## [1.2.0] - 2022-10-13

View File

@ -32,6 +32,8 @@
如果你希望使用原始的 sfxr 保存出的文件,请确保使用 `.sfxr` 扩展名保存。你也可以在原始的 sfxr 中加载并编辑 `.sfxr` 文件。
`.sfxr` 文件有循环Loop、位深度Bit Depth、采样率Sample Rate等导入选项。可以在 Godot 编辑器的导入面板中找到。
**注意:** 由于 GDScript 的性能限制,生成较长的音效时编辑器可能会有短暂的停滞。只有编辑器会受此影响。在游戏中使用 `.sfxr` 文件是不会在运行时生成任何东西的。
## 更新日志

View File

@ -42,6 +42,9 @@ But they can be used directly as regular `AudioStream`s.
If you want to reuse an existing sound from the original sfxr, make sure to save it with an
`.sfxr` extension. You can also load & edit the `.sfxr` file with the original sfxr.
Options for changing Looping, Bit Depth, and Sample Rate are available as import options
of the `.sfxr` file. You can find these options in Godot editor's Import dock.
**Note:** Due to performance constraints with GDScript, the editor may freeze a bit when generating
long sounds. This only happens in-editor.
Using `.sfxr` files in-game won't generate anything at runtime.

View File

@ -5,6 +5,15 @@ const SFXRConfig := preload("SFXRConfig.gd")
const master_vol := 0.05
enum WavBits {
WAV_BITS_8,
WAV_BITS_16,
}
enum WavFreq {
WAV_FREQ_44100,
WAV_FREQ_22050,
}
var _config: SFXRConfig
var rep_time: int
@ -41,32 +50,42 @@ var fltdmp: float
var fltphp: float
func generate_audio_stream(config: SFXRConfig) -> AudioStreamSample:
func generate_audio_stream(
config: SFXRConfig,
wav_bits: int = WavBits.WAV_BITS_8,
wav_freq: int = WavFreq.WAV_FREQ_44100
) -> AudioStreamSample:
var stream := AudioStreamSample.new()
stream.format = AudioStreamSample.FORMAT_8_BITS
stream.mix_rate = 44100
stream.format = AudioStreamSample.FORMAT_8_BITS if wav_bits == WavBits.WAV_BITS_8 else AudioStreamSample.FORMAT_16_BITS
stream.mix_rate = 44100 if wav_freq == WavFreq.WAV_FREQ_44100 else 22050
_config = config
stream.data = _generate_samples()
stream.data = _generate_samples(wav_bits, wav_freq).data_array
_config = null
return stream
func generate_samples(config: SFXRConfig) -> PoolByteArray:
func generate_samples(
config: SFXRConfig,
wav_bits: int = WavBits.WAV_BITS_8,
wav_freq: int = WavFreq.WAV_FREQ_44100
) -> PoolByteArray:
_config = config
var data := _generate_samples()
var data := _generate_samples(wav_bits, wav_freq).data_array
_config = null
return data
func _generate_samples() -> PoolByteArray:
func _generate_samples(wav_bits: int, wav_freq: int) -> StreamPeerBuffer:
_reset_sample(true)
var playing_sample := true
var env_stage := 0
var env_time := 0
var output := PoolByteArray([])
var filesample: float = 0
var fileacc := 0
var buffer := StreamPeerBuffer.new()
# SynthSample
while playing_sample:
@ -174,15 +193,21 @@ func _generate_samples() -> PoolByteArray:
ssample *= 4.0 # arbitrary gain to get reasonable output volume...
ssample = clamp(ssample, -1.0, +1.0)
var filesample := int((1 + ssample) / 2 * 255)
filesample += ssample
fileacc += 1
# This is a hack, AudioStreamSample wants a int8_t directly interpreted as uint8_t
filesample += 128
if filesample > 255:
filesample -= 255
if wav_freq == WavFreq.WAV_FREQ_44100 or fileacc == 2:
filesample /= fileacc
fileacc = 0
output.push_back(filesample)
return output
if wav_bits == WavBits.WAV_BITS_8:
buffer.put_8(filesample * 255)
else:
buffer.put_16(filesample * 32000)
filesample = 0
return buffer
func _reset_sample(restart: bool) -> void:

View File

@ -39,6 +39,18 @@ func get_import_options(preset):
name="loop",
default_value=false,
},
{
name="bit_depth",
property_hint=PROPERTY_HINT_ENUM,
hint_string="8 Bits,16 Bits",
default_value=SFXRGenerator.WavBits.WAV_BITS_8,
},
{
name="sample_rate",
property_hint=PROPERTY_HINT_ENUM,
hint_string="44100 Hz,22050 Hz",
default_value=SFXRGenerator.WavFreq.WAV_FREQ_44100,
},
]
@ -53,7 +65,9 @@ func import(source_file, save_path, options, platform_variants, gen_files):
printerr("Failed to open %s: %d" % [source_file, err])
return err
var stream := SFXRGenerator.new().generate_audio_stream(config)
var stream := SFXRGenerator.new().generate_audio_stream(
config, options.bit_depth, options.sample_rate
)
if options.loop:
stream.loop_mode = AudioStreamSample.LOOP_FORWARD
stream.loop_end = stream.data.size()

View File

@ -12,3 +12,5 @@ dest_files=[ "res://.import/example.sfxr-e3731bcdcd8403a2391e92667a5d1076.sample
[params]
loop=false
bit_depth=0
sample_rate=0