mirror of
https://github.com/Relintai/gdfxr.git
synced 2024-11-18 09:07:23 +01:00
Add import options for bit depth and sample rate
This commit is contained in:
parent
5b910afb64
commit
576708bb4a
@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
|
- Bit depth and sample rate import options.
|
||||||
- Paste from JSXFR.
|
- Paste from JSXFR.
|
||||||
|
|
||||||
## [1.2.0] - 2022-10-13
|
## [1.2.0] - 2022-10-13
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
如果你希望使用原始的 sfxr 保存出的文件,请确保使用 `.sfxr` 扩展名保存。你也可以在原始的 sfxr 中加载并编辑 `.sfxr` 文件。
|
如果你希望使用原始的 sfxr 保存出的文件,请确保使用 `.sfxr` 扩展名保存。你也可以在原始的 sfxr 中加载并编辑 `.sfxr` 文件。
|
||||||
|
|
||||||
|
`.sfxr` 文件有循环(Loop)、位深度(Bit Depth)、采样率(Sample Rate)等导入选项。可以在 Godot 编辑器的导入面板中找到。
|
||||||
|
|
||||||
**注意:** 由于 GDScript 的性能限制,生成较长的音效时编辑器可能会有短暂的停滞。只有编辑器会受此影响。在游戏中使用 `.sfxr` 文件是不会在运行时生成任何东西的。
|
**注意:** 由于 GDScript 的性能限制,生成较长的音效时编辑器可能会有短暂的停滞。只有编辑器会受此影响。在游戏中使用 `.sfxr` 文件是不会在运行时生成任何东西的。
|
||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
@ -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
|
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.
|
`.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
|
**Note:** Due to performance constraints with GDScript, the editor may freeze a bit when generating
|
||||||
long sounds. This only happens in-editor.
|
long sounds. This only happens in-editor.
|
||||||
Using `.sfxr` files in-game won't generate anything at runtime.
|
Using `.sfxr` files in-game won't generate anything at runtime.
|
||||||
|
@ -5,6 +5,15 @@ const SFXRConfig := preload("SFXRConfig.gd")
|
|||||||
|
|
||||||
const master_vol := 0.05
|
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 _config: SFXRConfig
|
||||||
|
|
||||||
var rep_time: int
|
var rep_time: int
|
||||||
@ -41,32 +50,42 @@ var fltdmp: float
|
|||||||
var fltphp: 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()
|
var stream := AudioStreamSample.new()
|
||||||
stream.format = AudioStreamSample.FORMAT_8_BITS
|
stream.format = AudioStreamSample.FORMAT_8_BITS if wav_bits == WavBits.WAV_BITS_8 else AudioStreamSample.FORMAT_16_BITS
|
||||||
stream.mix_rate = 44100
|
stream.mix_rate = 44100 if wav_freq == WavFreq.WAV_FREQ_44100 else 22050
|
||||||
|
|
||||||
_config = config
|
_config = config
|
||||||
stream.data = _generate_samples()
|
stream.data = _generate_samples(wav_bits, wav_freq).data_array
|
||||||
_config = null
|
_config = null
|
||||||
|
|
||||||
return stream
|
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
|
_config = config
|
||||||
var data := _generate_samples()
|
var data := _generate_samples(wav_bits, wav_freq).data_array
|
||||||
_config = null
|
_config = null
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
func _generate_samples() -> PoolByteArray:
|
func _generate_samples(wav_bits: int, wav_freq: int) -> StreamPeerBuffer:
|
||||||
_reset_sample(true)
|
_reset_sample(true)
|
||||||
|
|
||||||
var playing_sample := true
|
var playing_sample := true
|
||||||
var env_stage := 0
|
var env_stage := 0
|
||||||
var env_time := 0
|
var env_time := 0
|
||||||
var output := PoolByteArray([])
|
var filesample: float = 0
|
||||||
|
var fileacc := 0
|
||||||
|
var buffer := StreamPeerBuffer.new()
|
||||||
|
|
||||||
# SynthSample
|
# SynthSample
|
||||||
while playing_sample:
|
while playing_sample:
|
||||||
@ -174,15 +193,21 @@ func _generate_samples() -> PoolByteArray:
|
|||||||
ssample *= 4.0 # arbitrary gain to get reasonable output volume...
|
ssample *= 4.0 # arbitrary gain to get reasonable output volume...
|
||||||
ssample = clamp(ssample, -1.0, +1.0)
|
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
|
if wav_freq == WavFreq.WAV_FREQ_44100 or fileacc == 2:
|
||||||
filesample += 128
|
filesample /= fileacc
|
||||||
if filesample > 255:
|
fileacc = 0
|
||||||
filesample -= 255
|
|
||||||
|
if wav_bits == WavBits.WAV_BITS_8:
|
||||||
output.push_back(filesample)
|
buffer.put_8(filesample * 255)
|
||||||
return output
|
else:
|
||||||
|
buffer.put_16(filesample * 32000)
|
||||||
|
|
||||||
|
filesample = 0
|
||||||
|
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
|
||||||
func _reset_sample(restart: bool) -> void:
|
func _reset_sample(restart: bool) -> void:
|
||||||
|
@ -39,6 +39,18 @@ func get_import_options(preset):
|
|||||||
name="loop",
|
name="loop",
|
||||||
default_value=false,
|
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])
|
printerr("Failed to open %s: %d" % [source_file, err])
|
||||||
return 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:
|
if options.loop:
|
||||||
stream.loop_mode = AudioStreamSample.LOOP_FORWARD
|
stream.loop_mode = AudioStreamSample.LOOP_FORWARD
|
||||||
stream.loop_end = stream.data.size()
|
stream.loop_end = stream.data.size()
|
||||||
|
@ -12,3 +12,5 @@ dest_files=[ "res://.import/example.sfxr-e3731bcdcd8403a2391e92667a5d1076.sample
|
|||||||
[params]
|
[params]
|
||||||
|
|
||||||
loop=false
|
loop=false
|
||||||
|
bit_depth=0
|
||||||
|
sample_rate=0
|
||||||
|
Loading…
Reference in New Issue
Block a user