Overview
Comment: | Implement the user sounds (uncompressed) and MML sounds; does not work in the game yet, and built-in sounds are not yet implemented. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
5c902e7a3f5e25ce01b9318556568a75 |
User & Date: | user on 2022-01-15 05:59:20 |
Other Links: | manifest | tags |
Context
2022-01-16
| ||
03:11 | Some more fixes of sound effect including a few of documentation check-in: 45529d48c7 user: user tags: trunk | |
2022-01-15
| ||
05:59 | Implement the user sounds (uncompressed) and MML sounds; does not work in the game yet, and built-in sounds are not yet implemented. check-in: 5c902e7a3f user: user tags: trunk | |
2022-01-13
| ||
06:48 | Implement cryptographic hash algorithms. (These are not currently used by Free Hero Mesh but is expected to be used in future.) check-in: 1293433867 user: user tags: trunk | |
Changes
Modified compile from [552320bf15] to [8882a856f0].
︙ | ︙ | |||
13 14 15 16 17 18 19 | echo 'Flags: ' "$CFLAGS" echo 'Target filename: ' "$EXE" test instruc -nt instruc.h && node instruc.js > instruc.h test instruc.js -nt instruc.h && node instruc.js > instruc.h test names.js -nt names.h && node names.js > names.h test quarks -nt quarks.h && node quarks.js > quarks.h test quarks.js -nt quarks.h && node quarks.js > quarks.h | | < > > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | echo 'Flags: ' "$CFLAGS" echo 'Target filename: ' "$EXE" test instruc -nt instruc.h && node instruc.js > instruc.h test instruc.js -nt instruc.h && node instruc.js > instruc.h test names.js -nt names.h && node names.js > names.h test quarks -nt quarks.h && node quarks.js > quarks.h test quarks.js -nt quarks.h && node quarks.js > quarks.h test heromesh.h -nt "$EXE" && rm bindings.o class.o picture.o function.o exec.o game.o edit.o picedit.o sound.o || true test instruc.h -nt "$EXE" && rm class.o exec.o || true test pcfont.h -nt "$EXE" && rm picture.o || true test quarks.h -nt "$EXE" && rm bindings.o edit.o exec.o game.o picture.o picedit.o || true echo '* smallxrm' test smallxrm.c -nt smallxrm.o && bash smallxrm.c echo '* bindings' test bindings.c -nt bindings.o && bash bindings.c echo '* class' test class.c -nt class.o && bash class.c echo '* function' test function.c -nt function.o && bash function.c echo '* picture' test picture.c -nt picture.o && bash picture.c echo '* exec' test exec.c -nt exec.o && bash exec.c echo '* game' test game.c -nt game.o && bash game.c echo '* edit' test edit.c -nt edit.o && bash edit.c echo '* picedit' test picedit.c -nt picedit.o && bash picedit.c echo '* sound' test sound.c -nt sound.o && bash sound.c echo '* hash' test hash.c -nt hash.o && bash hash.c echo '* main' bash main.c echo 'DONE' |
Modified config.doc from [c3ec9417be] to [8852ef9b47].
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | === Resources === .altImage If the puzzle set contains multiple pictures with the same name and size then this resource controls which of those pictures is selected. The default setting is zero. .autoSave If true, saves changes to the level and solution files when the program terminates. If false (default), they are only saved to the user cache database; to copy the changes to the level and solution files, you must use the .u command in SQL mode (-x), or use the -f switch. .autoWin | > > > > > > > > > > > > > > > > > > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | === Resources === .altImage If the puzzle set contains multiple pictures with the same name and size then this resource controls which of those pictures is selected. The default setting is zero. .audio.buffer Buffer length for audio, as the number of samples. In order for audio to work at all, this value must be set. .audio.mmlTempo Define the number of quarter notes per minute. The default is 120. .audio.mmlTuning The MML tuning of the A4 note, in Hz. The default is 440 Hz, but some people do not like that tuning, so you can change it. .audio.mmlVolume MML volume, from 0 to 1; fractions are allowed. The default value is 1. .audio.rate Sample rate to use for audio, in hertz. In order for audio to work at all, this value must be set. .audio.waveVolume Wave volume, from 0 to 1; fractions are allowed. The default value is 1. .autoSave If true, saves changes to the level and solution files when the program terminates. If false (default), they are only saved to the user cache database; to copy the changes to the level and solution files, you must use the .u command in SQL mode (-x), or use the -f switch. .autoWin |
︙ | ︙ |
Modified heromesh.h from [0675ee5ddc] to [db1c986fad].
︙ | ︙ | |||
336 337 338 339 340 341 342 | void write_empty_level_set(FILE*); void batch_import(void); // == picedit == void run_picture_editor(void); | > > > > > > > > | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | void write_empty_level_set(FILE*); void batch_import(void); // == picedit == void run_picture_editor(void); // == sound == void init_sound(void); void set_sound_effect(Value v1,Value v2); Uint16 find_user_sound(const char*name); void set_sound_on(int on); void sound_test(void); |
Modified main.c from [f5412e16d8] to [c4bffb80c2].
1 | #if 0 | | | 1 2 3 4 5 6 7 8 9 | #if 0 gcc ${CFLAGS:--s -O2} -o ${EXE:-~/bin/heromesh} -Wno-multichar main.c class.o picture.o bindings.o function.o exec.o game.o edit.o picedit.o sound.o smallxrm.o hash.o sqlite3.o `sdl-config --cflags --libs` -ldl -lpthread -lm exit #endif /* This program is part of Free Hero Mesh and is public domain. */ |
︙ | ︙ | |||
868 869 870 871 872 873 874 875 876 877 878 879 880 881 | exit(0); break; case SDLK_s: goto scrolltest; case SDLK_t: puts(screen_prompt("Testing screen_prompt()")?:"No output."); break; } break; case SDL_MOUSEBUTTONDOWN: draw_picture(ev.button.x,ev.button.y,n); SDL_Flip(screen); break; case SDL_QUIT: | > > > > > > > > > > > | 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 | exit(0); break; case SDLK_s: goto scrolltest; case SDLK_t: puts(screen_prompt("Testing screen_prompt()")?:"No output."); break; case SDLK_u: set_sound_effect(UVALUE(n,TY_USOUND),NVALUE(0)); break; case SDLK_w: sound_test(); SDL_FillRect(screen,0,0); SDL_Flip(screen); break; case SDLK_z: set_sound_effect(NVALUE(0),NVALUE(1)); break; } break; case SDL_MOUSEBUTTONDOWN: draw_picture(ev.button.x,ev.button.y,n); SDL_Flip(screen); break; case SDL_QUIT: |
︙ | ︙ | |||
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 | run_picture_editor(); return 0; } if(main_options['z']) init_composite(); load_pictures(); if(main_options['T']) { printf("argv[0] = %s\n",argv[0]); test_mode(); return 0; } if(!main_options['z']) init_usercache(); if(main_options['n']) return 0; load_classes(); load_key_bindings(); load_level_index(); optionquery[1]=Q_maxObjects; max_objects=strtoll(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"",0,0)?:0xFFFF0000L; set_tracing(); annihilate(); | > > | 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 | run_picture_editor(); return 0; } if(main_options['z']) init_composite(); load_pictures(); if(main_options['T']) { printf("argv[0] = %s\n",argv[0]); init_sound(); test_mode(); return 0; } if(!main_options['z']) init_usercache(); if(main_options['n']) return 0; if(screen) init_sound(); load_classes(); load_key_bindings(); load_level_index(); optionquery[1]=Q_maxObjects; max_objects=strtoll(xrm_get_resource(resourcedb,optionquery,optionquery,2)?:"",0,0)?:0xFFFF0000L; set_tracing(); annihilate(); |
︙ | ︙ |
Modified quarks from [a64afd9280] to [64da450c8f].
︙ | ︙ | |||
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | ! Audio audio rate buffer mmlVolume waveVolume standardSounds ! Keyboard keyRepeat editKey gameKey ! Key codes | > > | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | ! Audio audio rate buffer mmlVolume waveVolume standardSounds mmlTuning mmlTempo ! Keyboard keyRepeat editKey gameKey ! Key codes |
︙ | ︙ |
Modified quarks.h from [e296cad002] to [ebbe12be54].
︙ | ︙ | |||
11 12 13 14 15 16 17 | #define Q_screenFlags 12 #define Q_audio 13 #define Q_rate 14 #define Q_buffer 15 #define Q_mmlVolume 16 #define Q_waveVolume 17 #define Q_standardSounds 18 | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | #define Q_screenFlags 12 #define Q_audio 13 #define Q_rate 14 #define Q_buffer 15 #define Q_mmlVolume 16 #define Q_waveVolume 17 #define Q_standardSounds 18 #define Q_mmlTuning 19 #define Q_mmlTempo 20 #define Q_keyRepeat 21 #define Q_editKey 22 #define Q_gameKey 23 #define Q_backspace 24 #define Q_tab 25 #define Q_clear 26 #define Q_return 27 #define Q_pause 28 #define Q_escape 29 #define Q_space 30 #define Q_exclaim 31 #define Q_quotedbl 32 #define Q_hash 33 #define Q_dollar 34 #define Q_ampersand 35 #define Q_quote 36 #define Q_leftparen 37 #define Q_rightparen 38 #define Q_asterisk 39 #define Q_plus 40 #define Q_comma 41 #define Q_minus 42 #define Q_period 43 #define Q_slash 44 #define Q_0 45 #define Q_1 46 #define Q_2 47 #define Q_3 48 #define Q_4 49 #define Q_5 50 #define Q_6 51 #define Q_7 52 #define Q_8 53 #define Q_9 54 #define Q_colon 55 #define Q_semicolon 56 #define Q_less 57 #define Q_equals 58 #define Q_greater 59 #define Q_question 60 #define Q_at 61 #define Q_leftbracket 62 #define Q_backslash 63 #define Q_rightbracket 64 #define Q_caret 65 #define Q_underscore 66 #define Q_backquote 67 #define Q_A 68 #define Q_B 69 #define Q_C 70 #define Q_D 71 #define Q_E 72 #define Q_F 73 #define Q_G 74 #define Q_H 75 #define Q_I 76 #define Q_J 77 #define Q_K 78 #define Q_L 79 #define Q_M 80 #define Q_N 81 #define Q_O 82 #define Q_P 83 #define Q_Q 84 #define Q_R 85 #define Q_S 86 #define Q_T 87 #define Q_U 88 #define Q_V 89 #define Q_W 90 #define Q_X 91 #define Q_Y 92 #define Q_Z 93 #define Q_delete 94 #define Q_kp0 95 #define Q_kp1 96 #define Q_kp2 97 #define Q_kp3 98 #define Q_kp4 99 #define Q_kp5 100 #define Q_kp6 101 #define Q_kp7 102 #define Q_kp8 103 #define Q_kp9 104 #define Q_kp_period 105 #define Q_kp_divide 106 #define Q_kp_multiply 107 #define Q_kp_minus 108 #define Q_kp_plus 109 #define Q_kp_enter 110 #define Q_kp_equals 111 #define Q_up 112 #define Q_down 113 #define Q_right 114 #define Q_left 115 #define Q_insert 116 #define Q_home 117 #define Q_end 118 #define Q_pageup 119 #define Q_pagedown 120 #define Q_f1 121 #define Q_f2 122 #define Q_f3 123 #define Q_f4 124 #define Q_f5 125 #define Q_f6 126 #define Q_f7 127 #define Q_f8 128 #define Q_f9 129 #define Q_f10 130 #define Q_f11 131 #define Q_f12 132 #define Q_f13 133 #define Q_f14 134 #define Q_f15 135 #define Q_numlock 136 #define Q_capslock 137 #define Q_scrollock 138 #define Q_rshift 139 #define Q_lshift 140 #define Q_rctrl 141 #define Q_lctrl 142 #define Q_ralt 143 #define Q_lalt 144 #define Q_rmeta 145 #define Q_lmeta 146 #define Q_lsuper 147 #define Q_rsuper 148 #define Q_mode 149 #define Q_help 150 #define Q_print 151 #define Q_sysreq 152 #define Q_break 153 #define Q_menu 154 #define Q_power 155 #define Q_euro 156 #define Q_compose 157 #define Q_undo 158 #define Q_shift 159 #define Q_ctrl 160 #define Q_alt 161 #define Q_meta 162 #define Q_numLock 163 #define Q_editClick 164 #define Q_gameClick 165 #define Q_allowMouseWarp 166 #define Q_middle 167 #define Q_class 168 #define Q_quiz 169 #define Q_saveSolutions 170 #define Q_solutionComment 171 #define Q_solutionTimestamp 172 #define Q_picedit 173 #define Q_macro 174 #define Q_sqlFile 175 #define Q_sqlInit 176 #define Q_sqlExtensions 177 #define Q_sqlMemStatus 178 #define Q_sqlSmallAllocations 179 #define Q_sqlCoveringIndexScan 180 #define Q_sqlPowerSafe 181 #define Q_level 182 #define Q_tracePrefix 183 #define Q_stackProtection 184 #define Q_maxObjects 185 #define Q_traceAll 186 #define Q_traceObject 187 #define Q_showInventory 188 #define Q_progress 189 #define Q_autoSave 190 #define Q_maxTrigger 191 #define Q_pasteCommand 192 #define Q_codepage 193 #define Q_replaySpeed 194 #define Q_autoWin 195 #define Q_listMode 196 #define Q_listColumns 197 static const char*const global_quarks[]={ "screenWidth", "screenHeight", "margin", "palette", "popupColors", "imageSize", "altImage", "editTitle", "gameTitle", "gamma", "screenFlags", "audio", "rate", "buffer", "mmlVolume", "waveVolume", "standardSounds", "mmlTuning", "mmlTempo", "keyRepeat", "editKey", "gameKey", "backspace", "tab", "clear", "return", |
︙ | ︙ |
Modified sound.c from [79607a175f] to [045a5b4883].
︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" #include "smallxrm.h" #include "quarks.h" #include "heromesh.h" typedef struct { Uint8*data; Uint32 len; // length in bytes } WaveSound; static Uint8 sound_on; | > | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" #include "smallxrm.h" #include "quarks.h" #include "heromesh.h" #include "cursorshapes.h" typedef struct { Uint8*data; Uint32 len; // length in bytes } WaveSound; static Uint8 sound_on; static Sint16 mmlvolume=9001; static SDL_AudioSpec spec; static WaveSound*standardsounds; static Uint16 nstandardsounds; static WaveSound*usersounds; static Uint16 nusersounds; static Uint8**user_sound_names; static FILE*l_fp; static long l_offset,l_size; static float wavevolume=1.0; static Uint8 needs_amplify=0; static Uint32*mmltuning; static Uint32 mmltempo; static Uint8*volatile wavesound; static volatile Uint32 wavelen; static volatile Uint8 mmlsound[512]; static volatile Uint16 mmlpos; static volatile Uint32 mmltime; static void audio_callback(void*userdata,Uint8*stream,int len) { static Uint32 phase; if(wavesound) { if(wavelen<=len) { memcpy(stream,wavesound,wavelen); memset(stream+wavelen,0,len-wavelen); wavesound=0; wavelen=0; } else { memcpy(stream,wavesound,len); wavesound+=len; wavelen-=len; } } else if(mmlpos) { Uint16*out=(Uint16*)stream; Uint32 t=mmltime; int re=len>>1; int m=mmlpos; int n=mmlsound[m-1]; memset(stream,0,len); while(re) { if(n!=255) { phase+=mmltuning[n]; if(t>1) *out=phase&0x80000000U?-mmlvolume:mmlvolume; } if(!--t) { m+=2; if(m>=512) { m=0; break; } n=mmlsound[m-1]; t=mmltempo*mmlsound[m]; if(!t) { m=0; break; } } out++; re--; } mmlpos=m; mmltime=t; } else { memset(stream,0,len); } } static int my_seek(SDL_RWops*cxt,int o,int w) { switch(w) { case RW_SEEK_SET: fseek(l_fp,l_offset+o,SEEK_SET); break; case RW_SEEK_CUR: fseek(l_fp,o,SEEK_CUR); break; case RW_SEEK_END: fseek(l_fp,l_offset+l_size+o,SEEK_SET); break; |
︙ | ︙ | |||
103 104 105 106 107 108 109 | cvt.buf=malloc(len*cvt.len_mult); cvt.len=len; if(!cvt.buf) goto fail; memcpy(cvt.buf,buf,len); if(SDL_ConvertAudio(&cvt)) goto fail; SDL_FreeWAV(buf); ws->data=cvt.buf; | | > < < > | | > | > > > > > > > > > | > > > > | | > > | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | cvt.buf=malloc(len*cvt.len_mult); cvt.len=len; if(!cvt.buf) goto fail; memcpy(cvt.buf,buf,len); if(SDL_ConvertAudio(&cvt)) goto fail; SDL_FreeWAV(buf); ws->data=cvt.buf; ws->len=cvt.len_cvt; amplify_wave_sound(ws); return; fail: if(main_options['v']) fprintf(stderr,"[Failed to convert wave audio at %ld (%ld bytes)]\n",offset,size); SDL_FreeWAV(buf); } static void load_sound_set(int is_user) { const char*v; char*nam; FILE*fp; Uint32 i,j; WaveSound*ws; if(is_user) { if(main_options['z']) { fp=composite_slice(".xclass",0); } else { nam=sqlite3_mprintf("%s.xclass",basefilename); if(!nam) return; fp=fopen(nam,"r"); sqlite3_free(nam); } if(!fp) return; } else { optionquery[2]=Q_standardSounds; v=xrm_get_resource(resourcedb,optionquery,optionquery,3); if(!v) return; fp=fopen(v,"r"); if(!fp) fatal("Cannot open standard sounds file (%m)\n"); nstandardsounds=50; standardsounds=malloc(nstandardsounds*sizeof(WaveSound)); if(!standardsounds) fatal("Allocation failed\n"); for(i=0;i<nstandardsounds;i++) standardsounds[i].data=0,standardsounds[i].len=0; } nam=malloc(256); for(;;) { for(i=0;;) { if(i==255) goto done; nam[i++]=j=fgetc(fp); if(j==(Uint32)EOF) goto done; if(!j) break; } i--; j=fgetc(fp)<<16; j|=fgetc(fp)<<24; j|=fgetc(fp)<<0; j|=fgetc(fp)<<8; l_offset=ftell(fp); l_size=j; if(i>4 && nam[i-4]=='.' && nam[i-3]=='W' && nam[i-1]=='V' && (nam[i-2]=='A' || nam[i-2]=='Z')) { j=nam[i-2]; nam[i-4]=0; if(is_user) { if(nusersounds>0x03FD) goto done; i=nusersounds++; usersounds=realloc(usersounds,nusersounds*sizeof(WaveSound)); user_sound_names=realloc(user_sound_names,nusersounds*sizeof(Uint8*)); if(!usersounds || !user_sound_names) fatal("Allocation failed\n"); user_sound_names[i]=strdup(nam); if(!user_sound_names[i]) fatal("Allocation failed\n"); ws=usersounds+i; ws->data=0; ws->len=0; } else { //TODO: Implement standard sounds. } if(j=='A') { load_sound(fp,l_offset,l_size,ws); } else { //TODO: Compressed sounds. } } fseek(fp,l_offset+l_size,SEEK_SET); } done: fclose(fp); free(nam); } void init_sound(void) { const char*v; double f; int i; optionquery[1]=Q_audio; optionquery[2]=Q_rate; v=xrm_get_resource(resourcedb,optionquery,optionquery,3); if(!v) return; spec.freq=strtol(v,0,10); optionquery[2]=Q_buffer; v=xrm_get_resource(resourcedb,optionquery,optionquery,3); |
︙ | ︙ | |||
197 198 199 200 201 202 203 | if(v=xrm_get_resource(resourcedb,optionquery,optionquery,3)) { needs_amplify=1; wavevolume=strtod(v,0); } optionquery[2]=Q_mmlVolume; if(v=xrm_get_resource(resourcedb,optionquery,optionquery,3)) mmlvolume=fmin(strtod(v,0)*32767.0,32767.0); if(wavevolume>0.00001) { | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | if(v=xrm_get_resource(resourcedb,optionquery,optionquery,3)) { needs_amplify=1; wavevolume=strtod(v,0); } optionquery[2]=Q_mmlVolume; if(v=xrm_get_resource(resourcedb,optionquery,optionquery,3)) mmlvolume=fmin(strtod(v,0)*32767.0,32767.0); if(wavevolume>0.00001) { //load_sound_set(0); // Standard sounds load_sound_set(1); // User sounds } if(mmlvolume) { mmltuning=malloc(256*sizeof(Uint32)); if(!mmltuning) fatal("Allocation failed\n"); optionquery[2]=Q_mmlTuning; if(v=xrm_get_resource(resourcedb,optionquery,optionquery,3)) f=strtod(v,0); else f=440.0; f*=0x80000000U/(double)spec.freq; for(i=0;i<256;i++) mmltuning[i]=f*pow(2.0,(i-96)/24.0); optionquery[2]=Q_mmlTempo; if(v=xrm_get_resource(resourcedb,optionquery,optionquery,3)) i=strtol(v,0,10); else i=120; // Convert quarter notes per minute to samples per sixty-fourth note mmltempo=(spec.freq*60)/(i*16); } fprintf(stderr,"Done.\n"); wavesound=0; mmlpos=0; SDL_PauseAudio(0); sound_on=1; } static void set_mml(const unsigned char*s) { const Sint8 y[8]={2,0,4,-18,-14,-10,-8,-4}; int m=0; int o=96; int t=2; int n; while(*s && m<512) { switch(*s++) { case '0' ... '8': o=24*(s[-1]-'0'); break; case '-': if(o) o-=24; break; case '+': o+=24; break; case '.': t+=t/2; break; case 'A' ... 'G': case 'a' ... 'g': n=o+y[s[-1]&7]; while(*s) switch(*s) { case '!': n-=2; s++; break; case '#': n+=2; s++; break; case ',': n-=1; s++; break; case '\'': n+=1; s++; break; default: goto send; } goto send; case 'H': case 'h': t=32; break; case 'I': case 'i': t=8; break; case 'L': case 'l': t=0; while(*s>='0' && *s<='9') t=10*t+*s++-'0'; break; case 'N': case 'n': n=0; while(*s>='0' && *s<='9') n=10*n+*s++-'0'; send: mmlsound[m++]=n; mmlsound[m++]=t; break; case 'Q': case 'q': t=16; break; case 'S': case 's': t=4; break; case 'T': case 't': t=2; break; case 'W': case 'w': t=64; break; case 'X': case 'x': mmlsound[m++]=255; mmlsound[m++]=t; break; case 'Z': case 'z': t=1; break; } } if(!m) return; if(m<511) mmlsound[m+1]=0; mmlpos=1; mmltime=mmlsound[1]*mmltempo; } void set_sound_effect(Value v1,Value v2) { static const unsigned char*const builtin[4]={ "s.g", "scdefgab+c-bagfedc-c", "i1c+c+c+c+c+c+c", "-cc'c#d,dd'd#ee'ff'f#", }; const unsigned char*s; if(!sound_on) return; if(!v2.t && !v2.u && (mmlpos || wavesound)) return; SDL_LockAudio(); wavesound=0; mmlpos=0; switch(v1.t) { case TY_SOUND: if(v1.u<nstandardsounds) { wavesound=standardsounds[v1.u].data; wavelen=standardsounds[v1.u].len; } break; case TY_USOUND: if(v1.u<nusersounds) { wavesound=usersounds[v1.u].data; wavelen=usersounds[v1.u].len; } break; case TY_STRING: case TY_LEVELSTRING: if(!mmlvolume) break; if(s=value_string_ptr(v1)) set_mml(s); break; case TY_FOR: // (only used for the sound test) if(!mmlvolume) break; set_mml(builtin[v1.u&3]); break; } SDL_UnlockAudio(); } Uint16 find_user_sound(const char*name) { int i; for(i=0;i<nusersounds;i++) if(!strcmp(name,user_sound_names[i])) return i+0x0400; return 0x03FF; } void set_sound_on(int on) { if(!sound_on) return; set_sound_effect(NVALUE(0),NVALUE(1)); SDL_PauseAudio(!on); } void sound_test(void) { Uint8 columns; SDL_Event ev; SDL_Rect r; int scroll=0; int nitems; int scrmax; int i,j,k,x,y; Value v; char buf[256]; if(main_options['T'] && main_options['v']) { if(mmltuning) printf("mmltempo=%d; mmlvolume=%d; mmltuning[96]=%d\n",(int)mmltempo,(int)mmlvolume,(int)mmltuning[96]); for(i=0;i<nusersounds;i++) printf("%d: %s (ptr=%p, len=%d bytes)\n",i,user_sound_names[i],usersounds[i].data,usersounds[i].len); fflush(stdout); } if(!screen) return; nitems=nusersounds+4; columns=(screen->w-16)/240?:1; scrmax=(nitems+columns-1)/columns; set_cursor(XC_arrow); redraw: SDL_FillRect(screen,0,0x02); r.x=r.y=0; r.w=screen->w; r.h=8; SDL_FillRect(screen,&r,0xF7); SDL_LockSurface(screen); draw_text(0,0," <F1> Mute <F2> Stop <F3> Status <ESC> Cancel",0xF7,0xF0); if(SDL_GetAudioStatus()==SDL_AUDIO_PLAYING) draw_text(0,0,"\x0E",0xF7,0xF1); for(i=scroll*columns,x=0,y=8;i<nitems;i++) { if(y>screen->h-24) break; if(i<nstandardsounds) { k=0xF9; snprintf(buf,29,"0"); //TODO } else if(i<nstandardsounds+nusersounds) { k=0xFA; snprintf(buf,29,"%s",user_sound_names[i-nstandardsounds]); } else { k=0xFB; snprintf(buf,29,"TEST %d",i-nstandardsounds-nusersounds); } r.x=x*240+20; r.y=y+4; r.w=232; r.h=16; SDL_FillRect(screen,&r,k); draw_text(r.x+4,r.y+4,buf,k,0xF0); if(++x==columns) x=0,y+=24; } SDL_UnlockSurface(screen); r.x=r.w=0; r.y=8; r.h=screen->h-8; scrollbar(&scroll,screen->h/8-1,scrmax,0,&r); SDL_Flip(screen); while(SDL_WaitEvent(&ev)) { if(ev.type!=SDL_VIDEOEXPOSE && scrollbar(&scroll,screen->h/8-1,scrmax,&ev,&r)) goto redraw; switch(ev.type) { case SDL_MOUSEMOTION: x=ev.button.x-16; y=ev.button.y-8; if(x<0 || y<0) goto arrow; i=x/240+columns*(y/24); x%=240; y%=24; if(x<4 || x>236 || y<4 || y>20 || i<0 || i>=nitems) goto arrow; set_cursor(XC_hand1); break; arrow: set_cursor(XC_arrow); break; case SDL_MOUSEBUTTONDOWN: x=ev.button.x-16; y=ev.button.y-8; if(x<0 || y<0) break; i=x/240+columns*(y/24); x%=240; y%=24; if(x<4 || x>236 || y<4 || y>20 || i<0 || i>=nitems) break; if(i<nstandardsounds) { v.t=TY_SOUND; v.u=i; } else if(i<nstandardsounds+nusersounds) { v.t=TY_USOUND; v.u=i-nstandardsounds; } else { v.t=TY_FOR; v.u=i-nstandardsounds-nusersounds; } set_sound_effect(v,NVALUE(ev.button.button-1)); break; case SDL_KEYDOWN: switch(ev.key.keysym.sym) { case SDLK_ESCAPE: return; case SDLK_F1: set_sound_on(SDL_GetAudioStatus()==SDL_AUDIO_PAUSED); goto redraw; case SDLK_F2: set_sound_effect(NVALUE(0),NVALUE(1)); break; case SDLK_F3: snprintf(buf,255,"Sample rate: %d Hz\nBuffer size: %d samples (%d bytes)\nStatus: %d\nWave queue: %d bytes\nMML position: %d" ,(int)spec.freq,(int)spec.samples,(int)spec.size,(int)SDL_GetAudioStatus(),(int)wavelen,(int)mmlpos); modal_draw_popup(buf); goto redraw; case SDLK_HOME: case SDLK_KP7: scroll=0; goto redraw; } break; case SDL_VIDEOEXPOSE: goto redraw; case SDL_QUIT: SDL_PushEvent(&ev); return; } } } |