Files
nethack/include/sndprocs.h
nhmall 5e0fea186c further utilize sound interface - part 2
Expand windsound to support SNDCAP_USERSOUNDS (existing),
SNDCAP_SOUNDEFFECTS, SNDCAP_HEROMUSIC.

Place a small number of wav files into sound/wav that are considered
more specific to some game stuff in the core, namely: playing
instruments by the hero, squeaky board traps. The intention is that
those ones can be integrated into the game without requiring user
file deposits or mappings. Building soundlib support for sound/windsound
searches for them as resources, so they should "just work."

No actual instrument playback is available in the base sound/windsound
soundlib implementation (yet, at least), so it works around that in
a cheap way by using the note-variant wav sounds to concoct the
notes. There are better ways of doing music generation than that,
of course, but this will do in the early going. Any other soundlib
port (such as Qt) can probably easily do the exact same thing. If it
can play USER_SOUNDS, it can almost certainly use the
sound/wav/se_squeak*.wav and sound/wav/sound_*.wav files for
SND_HEROMUSIC and squeaky board sounds soundeffects.

A few of the se_ sounds in sound/wav are free yet licensed, and
there is a file called attributions.txt to meticulously attempt
to comply with the two license variations involved.

SND_SOUNDEFFECTS_AUTOMAP

If SND_SOUNDEFFECTS_AUTOMAP is defined, and a SND_LIB_ interface
that supports SNDPROC_SOUNDEFFECTS is also defined to integrate
soundlib support, the following gets added:

  o If sounddir is defined (existing longstanding feature that's
    been used with USER_SOUNDS for many, many years) any wav file
    present in SOUNDDIR with a name that matches one of the defined
    sound effects in include/sndproc.h will get played each time
    that soundeffect comes up. So, just drop appropriate wav files
    into sounddir and rename it to match.

    No tedious config file entries are required to get soundeffects.

    [ The only config file change required is to
      set SOUNDDIR to point to your directory with the wav files.
      Note: SOUNDDIR only works in your config file if NetHack
      was built with USER_SOUNDS defined. ]

    This is new so there may certainly be some bugs in here.
    Please kindly report them if you encounter any.

    For those that don't read C very well, these are the file names
    that should trigger the SOUNDEFFECTS_AUTOMAP, assuming it is working.

        se_faint_splashing.wav
        se_crackling_of_hellfire.wav
        se_heart_beat.wav
        se_typing_noise.wav
        se_hollow_sound.wav
        se_rustling_paper.wav
        se_crushing_sound.wav
        se_splash.wav
        se_chains_rattling_gears_turning.wav
        se_smashing_and_crushing.wav
        se_gears_turning_chains_rattling.wav
        se_loud_splash.wav
        se_lound_crash.wav
        se_crashing_rock.wav
        se_sizzling.wav
        se_crashing_boulder.wav
        se_boulder_drop.wav
        se_item_tumble_downwards.wav
        se_drain_noises.wav
        se_ring_in_drain.wav
        se_groans_and_moans.wav
        se_scratching.wav
        se_glass_shattering.wav
        se_egg_cracking.wav
        se_gushing_sound.wav
        se_glass_crashing.wav
        se_egg_splatting.wav
        se_sinister_laughter.wav
        se_blast.wav
        se_stone_breaking.wav
        se_stone_crumbling.wav
        se_snakes_hissing.wav
        se_loud_pop.wav
        se_clanking_pipe.wav
        se_sewer_song.wav
        se_monster_behind_boulder.wav
        se_wailing_of_the_banshee.wav
        se_swoosh.wav
        se_explosion.wav
        se_crashing_sound.wav
        se_someone_summoning.wav
        se_rushing_wind_noise.wav
        se_splat_from_engulf.wav
        se_faint_sloshing.wav
        se_crunching_sound.wav
        se_slurping_sound.wav
        se_masticating_sound.wav
        se_distant_thunder.wav
        se_applause.wav
        se_shrill_whistle.wav
        se_someone_yells.wav
        se_door_unlock_and_open.wav
        se_door_open.wav
        se_door_crash_open.wav
        se_dry_throat_rattle.wav
        se_cough.wav
        se_angry_snakes.wav
        se_zap_then_explosion.wav
        se_zap.wav
        se_horn_being_played.wav
        se_mon_chugging_potion.wav
        se_bugle_playing_reveille.wav
        se_crash_through_floor.wav
        se_thump.wav
        se_scream.wav
        se_tumbler_click.wav
        se_gear_turn.wav
        se_divine_music.wav
        se_thunderclap.wav
        se_sad_wailing.wav
        se_maniacal_laughter.wav
        se_rumbling_of_earth.wav
        se_clanging_sound.wav
        se_mutter_imprecations.wav
        se_mutter_incantation.wav
        se_angry_voice.wav
        se_sceptor_pounding.wav
        se_courtly_conversation.wav
        se_low_buzzing.wav
        se_angry_drone.wav
        se_bees.wav
        se_someone_searching.wav
        se_guards_footsteps.wav
        se_faint_chime.wav
        se_loud_click.wav
        se_soft_click.wav
        se_squeak.wav
        se_squeak_C.wav
        se_squeak_D_flat.wav
        se_squeak_D.wav
        se_squeak_E_flat.wav
        se_squeak_E.wav
        se_squeak_F.wav
        se_squeak_F_sharp.wav
        se_squeak_G.wav
        se_squeak_G_sharp.wav
        se_squeak_A.wav
        se_squeak_B_flat.wav
        se_squeak_B.wav
        se_someone_bowling.wav
        se_rumbling.wav
        se_loud_crash.wav
        se_deafening_roar_atmospheric.wav
        se_low_hum.wav
        se_laughter.wav
        se_cockatrice_hiss.wav
        se_chant.wav
        se_cracking_sound.wav
        se_ripping_sound.wav
        se_thud.wav
        se_clank.wav
        se_crumbling_sound.wav
        se_soft_crackling.wav
        se_crackling.wav
        se_sharp_crack.wav
        se_wall_of_force.wav
        se_alarm.wav
        se_kick_door_it_shatters.wav
        se_kick_door_it_crashes_open.wav
        se_bubble_rising.wav
        se_bolt_of_lightning.wav
        se_board_squeak.wav
        se_board_squeaks_loudly.wav
        se_boing.wav
        se_crashed_ceiling.wav
        se_clash.wav
        se_crash_door.wav
        se_crash.wav
        se_crash_throne_destroyed.wav
        se_crash_something_broke.wav
        se_kadoom_boulder_falls_in.wav
        se_klunk_pipe.wav
        se_kerplunk_boulder_gone.wav
        se_klunk.wav
        se_klick.wav
        se_kaboom_door_explodes.wav
        se_kaboom_boom_boom.wav
        se_kaablamm_of_mine.wav
        se_kaboom.wav
        se_splat_egg.wav
        se_destroy_web.wav
        se_iron_ball_dragging_you.wav
        se_iron_ball_hits_you.wav
        se_lid_slams_open_falls_shut.wav
        se_chain_shatters.wav
        se_furious_bubbling.wav
        se_air_crackles.wav
        se_potion_crash_and_break.wav
        se_hiss.wav
        se_growl.wav
        se_canine_bark.wav
        se_canine_growl.wav
        se_canine_whine.wav
        se_canine_yip.wav
        se_canine_howl.wav
        se_feline_yowl.wav
        se_feline_meow.wav
        se_feline_purr.wav
        se_feline_yip.wav
        se_feline_mew.wav
        se_roar.wav
        se_snarl.wav
        se_buzz.wav
        se_squeek.wav
        se_squawk.wav
        se_squeal.wav
        se_screech.wav
        se_equine_neigh.wav
        se_equine_whinny.wav
        se_equine_whicker.wav
        se_bovine_moo.wav
        se_bovine_bellow.wav
        se_wail.wav
        se_groan.wav
        se_grunt.wav
        se_gurgle.wav
        se_elephant_trumpet.wav
        se_snake_rattle.wav
        se_hallu_growl.wav

This needs further testing. At the moment only windsound has
this.

If nobody else looks into it for Qt, I'll take a look in a
few days.
2023-01-22 13:29:44 -05:00

404 lines
17 KiB
C

/* NetHack 3.7 sndprocs.h $NHDT-Date: $ $NHDT-Branch: $:$NHDT-Revision: $ */
/* Copyright (c) Michael Allison, 2022 */
/* NetHack may be freely redistributed. See license for details. */
#ifndef SNDPROCS_H
#define SNDPROCS_H
/*
*
* Types of potential sound supports (all are optional):
*
* SNDCAP_USERSOUNDS User-specified sounds that play based on config
* file entries that identify a regular expression
* to match against message window text, and identify
* an external sound file to load in response.
* The sound interface function pointer used to invoke
* it:
*
* void (*sound_play_usersound)(char *filename,
* int32_t volume, int32_t idx);
*
* SNDCAP_HEROMUSIC Invoked by the core when the in-game hero is
* playing a tune on an instrument. The sound
* interface function pointer used to invoke it:
*
* void (*sound_hero_playnotes)(int32_t instrument,
* char *str, int32_t volume);
*
* SNDCAP_ACHIEVEMENTS Invoked by the core when an in-game achievement
* is reached. The soundlib routines could play
* appropriate theme or mood music in response.
* There would need to be a way to map the
* achievements to external user-specified sounds.
* The sound interface function pointer used to
* invoke it:
*
* void (*sound_achievement)(schar, schar,
* int32_t);
*
* SNDCAP_SOUNDEFFECTS Invoked by the core when something
* sound-producing happens in the game. The soundlib
* routines could play an appropriate sound effect
* in response. They can be public-domain or
* suitably-licensed stock sounds included with the
* game source and made available during the build
* process, or (not-yet-implemented) a way to
* tie particular sound effects to a user-specified
* sound samples in a config file. The sound
* interface function pointer used to invoke it:
*
* void (*sound_soundeffect)(char *desc, int32_t,
* int32_t volume);
*
* Development notes:
* - gc.chosen_soundlib holds the soundlib_id that will be initialized
* at the appropriate time (startup or after an option change). It
* is initialized to soundlib_nosound, so that is what will be used if
* the initial value isn't replaced via an assign_soundlib() call
* prior to the call to the activate_chosen_soundlib() in
* moveloop_preamble() at the start of the game.
* - ga.active_soundlib holds the soundlib_id of the active soundlib.
* It is initialized to soundlib_unassigned. It will get changed to
* reflect the activated soundlib_id once activate_chosen_soundlib()
* has been called.
*
*/
enum soundlib_ids {
soundlib_unassigned = 0,
#ifdef SND_LIB_QTSOUND
soundlib_qtsound,
#endif
#ifdef SND_LIB_PORTAUDIO
soundlib_portaudio,
#endif
#ifdef SND_LIB_OPENAL
soundlib_openal,
#endif
#ifdef SND_LIB_SDL_MIXER
soundlib_sdl_mixer,
#endif
#ifdef SND_LIB_MINIAUDIO
soundlib_miniaudio,
#endif
#ifdef SND_LIB_FMOD
soundlib_fmod,
#endif
#ifdef SND_LIB_SOUND_ESCCODES
soundlib_sound_esccodes,
#endif
#ifdef SND_LIB_VISSOUND
soundlib_vissound,
#endif
#ifdef SND_LIB_WINDSOUND
soundlib_windsound,
#endif
soundlib_nosound
};
struct sound_procs {
const char *soundname;
enum soundlib_ids soundlib_id;
unsigned long sndcap; /* capabilities in the port */
void (*sound_init_nhsound)(void);
void (*sound_exit_nhsound)(const char *);
void (*sound_achievement)(schar, schar, int32_t);
void (*sound_soundeffect)(char *desc, int32_t, int32_t volume);
void (*sound_hero_playnotes)(int32_t instrument, char *str, int32_t volume);
void (*sound_play_usersound)(char *filename, int32_t volume, int32_t idx);
};
extern struct sound_procs sndprocs;
#define SOUNDID(soundname) #soundname, soundlib_##soundname
/*
* SOUNDCAP
*/
#define SNDCAP_USERSOUNDS 0x0001L
#define SNDCAP_HEROMUSIC 0x0002L
#define SNDCAP_ACHIEVEMENTS 0x0004L
#define SNDCAP_SOUNDEFFECTS 0x0008L
/* 28 free bits */
extern struct sound_procs soundprocs;
/* subset for NetHack */
enum instruments {
ins_cello = 43, ins_orchestral_harp = 47, ins_choir_aahs = 53,
ins_trumpet = 57, ins_trombone = 58, ins_french_horn = 61,
ins_baritone_sax = 68, ins_english_horn = 70, ins_piccolo = 73,
ins_flute = 74, ins_pan_flute = 76, ins_blown_bottle = 77,
ins_whistle = 79, ins_tinkle_bell = 113, ins_woodblock = 116,
ins_taiko_drum = 117, ins_melodic_tom = 118, ins_seashore = 123,
ins_no_instrument
};
#if 0
enum instruments_broad {
ins_acoustic_grand_piano = 1, ins_bright_acoustic_piano = 2,
ins_electric_grand_piano = 3, ins_honkytonk_piano = 4,
ins_electric_piano_1 = 5, ins_electric_piano_2 = 6,
ins_harpsichord = 7, ins_clavinet = 8, ins_celesta = 9,
ins_glockenspiel = 10, ins_music_box = 11, ins_vibraphone = 12,
ins_marimba = 13, ins_xylophone = 14, ins_tubular_bells = 15,
ins_dulcimer = 16, ins_drawbar_organ = 17,
ins_percussive_organ = 18, ins_rock_organ = 19, ins_church_organ = 20,
ins_reed_organ = 21, ins_french_accordion = 22, ins_harmonica = 23,
ins_tango_accordion = 24, ins_acoustic_guitar__nylon = 25,
ins_acoustic_guitar_steel = 26, ins_electric_guitar_jazz = 27,
ins_electric_guitar_clean = 28, ins_electric_guitar_muted = 29,
ins_overdriven_guitar = 30, ins_distortion_guitar = 31,
ins_guitar_harmonics = 32, ins_acoustic_bass = 33,
ins_electric_bass__fingered = 34, ins_electric_bass_picked = 35,
ins_fretless_bass = 36, ins_slap_bass_1 = 37, ins_slap_bass_2 = 38,
ins_synth_bass_1 = 39, ins_synth_bass_2 = 40, ins_violin = 41,
ins_viola = 42, ins_cello = 43, ins_contrabass = 44,
ins_tremolo_strings = 45, ins_pizzicato_strings = 46,
ins_orchestral_harp = 47, ins_timpani = 48,
ins_string_ensemble_1 = 49, ins_string_ensemble_2 = 50,
ins_synthstrings_1 = 51, ins_synthstrings_2 = 52, ins_choir_aahs = 53,
ins_voice_oohs = 54, ins_synth_voice = 55, ins_orchestra_hit = 56,
ins_trumpet = 57, ins_trombone = 58, ins_tuba = 59, ins_muted_trumpet = 60,
ins_french_horn = 61, ins_brass_section = 62, ins_synthbrass_1 = 63,
ins_synthbrass_2 = 64, ins_soprano_sax = 65, ins_alto_sax = 66,
ins_tenor_sax = 67, ins_baritone_sax = 68, ins_oboe = 69,
ins_english_horn = 70, ins_bassoon = 71, ins_clarinet = 72,
ins_piccolo = 73, ins_flute = 74, ins_recorder = 75,
ins_pan_flute = 76, ins_blown_bottle = 77, ins_shakuhachi = 78,
ins_whistle = 79, ins_ocarina = 80, ins_sitar = 105, ins_banjo = 106,
ins_shamisen = 107, ins_koto = 108, ins_kalimba = 109, ins_bag_pipe = 110,
ins_fiddle = 111, ins_shanai = 112, ins_tinkle_bell = 113, ins_agogo = 114,
ins_steel_drums = 115, ins_woodblock = 116, ins_taiko_drum = 117,
ins_melodic_tom = 118, ins_synth_drum = 119, ins_reverse_cymbal = 120,
ins_guitar_fret_noise = 121, ins_breath_noise = 122, ins_seashore = 123,
ins_bird_tweet = 124, ins_telephone_ring = 125, ins_helicopter = 126,
ins_applause = 127, ins_gunshot = 128,
ins_no_instrument
};
#endif
enum sound_effect_entries {
se_zero_invalid = 0,
se_faint_splashing = 1,
se_crackling_of_hellfire = 2,
se_heart_beat = 3,
se_typing_noise = 4,
se_hollow_sound = 5,
se_rustling_paper = 6,
se_crushing_sound = 7,
se_splash = 8,
se_chains_rattling_gears_turning = 9,
se_smashing_and_crushing = 10,
se_gears_turning_chains_rattling = 11,
se_loud_splash = 12,
se_lound_crash = 13,
se_crashing_rock = 14,
se_sizzling = 15,
se_crashing_boulder = 16,
se_boulder_drop = 17,
se_item_tumble_downwards = 18,
se_drain_noises = 19,
se_ring_in_drain = 20,
se_groans_and_moans = 21,
se_scratching = 22,
se_glass_shattering = 23,
se_egg_cracking = 24,
se_gushing_sound = 25,
se_glass_crashing = 26,
se_egg_splatting = 27,
se_sinister_laughter = 28,
se_blast = 29,
se_stone_breaking = 30,
se_stone_crumbling = 31,
se_snakes_hissing = 32,
se_loud_pop = 33,
se_clanking_pipe = 34,
se_sewer_song = 35,
se_monster_behind_boulder = 36,
se_wailing_of_the_banshee = 37,
se_swoosh = 38,
se_explosion = 39,
se_crashing_sound = 40,
se_someone_summoning = 41,
se_rushing_wind_noise = 42,
se_splat_from_engulf = 43,
se_faint_sloshing = 44,
se_crunching_sound = 45,
se_slurping_sound = 46,
se_masticating_sound = 47,
se_distant_thunder = 48,
se_applause = 49,
se_shrill_whistle = 50,
se_someone_yells = 51,
se_door_unlock_and_open = 52,
se_door_open = 53,
se_door_crash_open = 54,
se_dry_throat_rattle = 55,
se_cough = 56,
se_angry_snakes = 57,
se_zap_then_explosion = 58,
se_zap = 59,
se_horn_being_played = 60,
se_mon_chugging_potion = 61,
se_bugle_playing_reveille = 62,
se_crash_through_floor = 63,
se_thump = 64,
se_scream = 65,
se_tumbler_click = 66,
se_gear_turn = 67,
se_divine_music = 68,
se_thunderclap = 69,
se_sad_wailing = 70,
se_maniacal_laughter = 71,
se_rumbling_of_earth = 72,
se_clanging_sound = 73,
se_mutter_imprecations = 74,
se_mutter_incantation = 75,
se_angry_voice = 76,
se_sceptor_pounding = 77,
se_courtly_conversation = 78,
se_low_buzzing = 79,
se_angry_drone = 80,
se_bees = 81,
se_someone_searching = 82,
se_guards_footsteps = 83,
se_faint_chime = 84,
se_loud_click = 85,
se_soft_click = 86,
se_squeak = 87,
se_squeak_C = 88,
se_squeak_D_flat = 89,
se_squeak_D = 90,
se_squeak_E_flat = 91,
se_squeak_E = 92,
se_squeak_F = 93,
se_squeak_F_sharp = 94,
se_squeak_G = 95,
se_squeak_G_sharp = 96,
se_squeak_A = 97,
se_squeak_B_flat = 98,
se_squeak_B = 99,
se_someone_bowling = 100,
se_rumbling = 101,
se_loud_crash = 102,
se_deafening_roar_atmospheric = 103,
se_low_hum = 104,
se_laughter = 105,
se_cockatrice_hiss = 106,
se_chant = 107,
se_cracking_sound = 108,
se_ripping_sound = 109,
se_thud = 110,
se_clank = 111,
se_crumbling_sound = 112,
se_soft_crackling = 113,
se_crackling = 114,
se_sharp_crack = 115,
se_wall_of_force = 116,
se_alarm = 117,
se_kick_door_it_shatters = 118,
se_kick_door_it_crashes_open = 119,
se_bubble_rising = 120,
se_bolt_of_lightning = 121,
se_board_squeak = 122,
se_board_squeaks_loudly = 123,
se_boing = 124,
se_crashed_ceiling = 125,
se_clash = 126,
se_crash_door = 127,
se_crash = 128,
se_crash_throne_destroyed = 129,
se_crash_something_broke = 130,
se_kadoom_boulder_falls_in = 131,
se_klunk_pipe = 132,
se_kerplunk_boulder_gone = 133,
se_klunk = 134,
se_klick = 135,
se_kaboom_door_explodes = 136,
se_kaboom_boom_boom = 137,
se_kaablamm_of_mine = 138,
se_kaboom = 139,
se_splat_egg = 140,
se_destroy_web = 141,
se_iron_ball_dragging_you = 142,
se_iron_ball_hits_you = 143,
se_lid_slams_open_falls_shut = 144,
se_chain_shatters = 145,
se_furious_bubbling = 146,
se_air_crackles = 147,
se_potion_crash_and_break = 148,
se_hiss = 149,
se_growl = 150,
se_canine_bark = 151,
se_canine_growl = 152,
se_canine_whine = 153,
se_canine_yip = 154,
se_canine_howl = 155,
se_feline_yowl = 156,
se_feline_meow = 157,
se_feline_purr = 158,
se_feline_yip = 159,
se_feline_mew = 160,
se_roar = 161,
se_snarl = 162,
se_buzz = 163,
se_squeek = 164,
se_squawk = 165,
se_squeal = 166,
se_screech = 167,
se_equine_neigh = 168,
se_equine_whinny = 169,
se_equine_whicker = 170,
se_bovine_moo = 171,
se_bovine_bellow = 172,
se_wail = 173,
se_groan = 174,
se_grunt = 175,
se_gurgle = 176,
se_elephant_trumpet = 177,
se_snake_rattle = 178,
se_hallu_growl = 179,
number_of_se_entries
};
#if defined(SND_LIB_QTSOUND) || defined(SND_LIB_PORTAUDIO) \
|| defined(SND_LIB_OPENAL) || defined(SND_LIB_SDL_MIXER) \
|| defined(SND_LIB_MINIAUDIO) || defined(SND_LIB_FMOD) \
|| defined(SND_LIB_SOUND_ESCCODES) || defined(SND_LIB_VISSOUND) \
|| defined(SND_LIB_WINDSOUND)
#define SND_LIB_INTEGRATED /* shortcut for conditional code in other files */
#define Play_usersound(filename, vol, idx) \
do { \
if (!Deaf && soundprocs.sound_play_usersound \
&& ((soundprocs.sndcap & SNDCAP_USERSOUNDS) != 0)) \
(*soundprocs.sound_play_usersound)((filename), (vol), (idx)); \
} while(0)
#define Soundeffect(seid, vol) \
do { \
if (!Deaf && soundprocs.sound_soundeffect \
&& ((soundprocs.sndcap & SNDCAP_SOUNDEFFECTS) != 0)) \
(*soundprocs.sound_soundeffect)(emptystr, (seid), (vol)); \
} while(0)
#define Hero_playnotes(instrument, str, vol) \
do { \
if (!Deaf && soundprocs.sound_hero_playnotes \
&& ((soundprocs.sndcap & SNDCAP_HEROMUSIC) != 0)) \
(*soundprocs.sound_hero_playnotes)((instrument), (str), (vol)); \
} while(0)
#else
#ifdef SND_LIB_INTEGRATED
#undef SND_LIB_INTEGRATED
#endif
#define Play_usersound(filename, vol, idx)
#define Soundeffect(seid, vol)
#define Hero_playnotes(instrument, str, vol)
#endif
#endif /* SNDPROCS_H */