Artifact 4ad5c2248e4b834668dcca2bea95eda0780edaf343849f7bf2184b409872d5a3:
- File
src/sound.m
— part of check-in
[6b85eefc85]
at
2025-03-23 02:47:40
on branch trunk
— Remove loop[ijkl]
They confused clang-format a lot. (user: js, size: 4228) [annotate] [blame] [check-ins using]
#include "cube.h" #import "DynamicEntity.h" #include <SDL_mixer.h> VARP(soundvol, 0, 255, 255); VARP(musicvol, 0, 128, 255); bool nosound = false; #define MAXCHAN 32 #define SOUNDFREQ 22050 #define MAXVOL MIX_MAX_VOLUME struct soundloc { OFVector3D loc; bool inuse; } soundlocs[MAXCHAN]; static Mix_Music *mod = NULL; void stopsound() { if (nosound) return; if (mod != NULL) { Mix_HaltMusic(); Mix_FreeMusic(mod); mod = NULL; } } VAR(soundbufferlen, 128, 1024, 4096); void initsound() { memset(soundlocs, 0, sizeof(struct soundloc) * MAXCHAN); if (Mix_OpenAudio(SOUNDFREQ, MIX_DEFAULT_FORMAT, 2, soundbufferlen) < 0) { conoutf(@"sound init failed (SDL_mixer): %s", (size_t)Mix_GetError()); nosound = true; } Mix_AllocateChannels(MAXCHAN); } void music(OFString *name) { if (nosound) return; stopsound(); if (soundvol && musicvol) { name = [name stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]; OFString *path = [OFString stringWithFormat:@"packages/%@", name]; OFIRI *IRI = [Cube.sharedInstance.gameDataIRI IRIByAppendingPathComponent:path]; if ((mod = Mix_LoadMUS( IRI.fileSystemRepresentation.UTF8String)) != NULL) { Mix_PlayMusic(mod, -1); Mix_VolumeMusic((musicvol * MAXVOL) / 255); } } } COMMAND(music, ARG_1STR) static OFMutableData *samples; static OFMutableArray<OFString *> *snames; int registersound(OFString *name) { int i = 0; for (OFString *iter in snames) { if ([iter isEqual:name]) return i; i++; } if (snames == nil) snames = [[OFMutableArray alloc] init]; if (samples == nil) samples = [[OFMutableData alloc] initWithItemSize:sizeof(Mix_Chunk *)]; [snames addObject:[name stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]]; Mix_Chunk *sample = NULL; [samples addItem:&sample]; return samples.count - 1; } COMMAND(registersound, ARG_1EST) void cleansound() { if (nosound) return; stopsound(); Mix_CloseAudio(); } VAR(stereo, 0, 1, 1); static void updatechanvol(int chan, const OFVector3D *loc) { int vol = soundvol, pan = 255 / 2; if (loc) { vdist(dist, v, *loc, player1.origin); vol -= (int)(dist * 3 * soundvol / 255); // simple mono distance attenuation if (stereo && (v.x != 0 || v.y != 0)) { // relative angle of sound along X-Y axis float yaw = -atan2(v.x, v.y) - player1.yaw * (PI / 180.0f); // range is from 0 (left) to 255 (right) pan = (int)(255.9f * (0.5 * sin(yaw) + 0.5f)); } } vol = (vol * MAXVOL) / 255; Mix_Volume(chan, vol); Mix_SetPanning(chan, 255 - pan, pan); } static void newsoundloc(int chan, const OFVector3D *loc) { assert(chan >= 0 && chan < MAXCHAN); soundlocs[chan].loc = *loc; soundlocs[chan].inuse = true; } void updatevol() { if (nosound) return; for (int i = 0; i < MAXCHAN; i++) { if (soundlocs[i].inuse) { if (Mix_Playing(i)) updatechanvol(i, &soundlocs[i].loc); else soundlocs[i].inuse = false; } } } void playsoundc(int n) { addmsg(0, 2, SV_SOUND, n); playsound(n, NULL); } int soundsatonce = 0, lastsoundmillis = 0; void playsound(int n, const OFVector3D *loc) { if (nosound) return; if (!soundvol) return; if (lastmillis == lastsoundmillis) soundsatonce++; else soundsatonce = 1; lastsoundmillis = lastmillis; if (soundsatonce > 5) // avoid bursts of sounds with heavy packetloss and in sp return; if (n < 0 || n >= samples.count) { conoutf(@"unregistered sound: %d", n); return; } Mix_Chunk **sample = (Mix_Chunk **)[samples mutableItemAtIndex:n]; if (*sample == NULL) { OFString *path = [OFString stringWithFormat:@"packages/sounds/%@.wav", snames[n]]; OFIRI *IRI = [Cube.sharedInstance.gameDataIRI IRIByAppendingPathComponent:path]; *sample = Mix_LoadWAV(IRI.fileSystemRepresentation.UTF8String); if (*sample == NULL) { conoutf(@"failed to load sample: %@", IRI.string); return; } } int chan = Mix_PlayChannel(-1, *sample, 0); if (chan < 0) return; if (loc) newsoundloc(chan, loc); updatechanvol(chan, loc); } void sound(int n) { playsound(n, NULL); } COMMAND(sound, ARG_1INT)