model_shared: Avoid Mod_MakeSortedSurfaces if dedicated. Fixes crash.
[xonotic/darkplaces.git] / snd_mem.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21
22 #include "darkplaces.h"
23
24 #include "snd_main.h"
25 #include "snd_ogg.h"
26 #include "snd_wav.h"
27 #ifdef USEXMP
28 #include "snd_xmp.h"
29 #endif
30 #include "sound.h"
31
32 void SCR_PushLoadingScreen (const char *, float);
33 void SCR_PopLoadingScreen (qbool);
34
35 /*
36 ====================
37 Snd_CreateRingBuffer
38
39 If "buffer" is NULL, the function allocates one buffer of "sampleframes" sample frames itself
40 (if "sampleframes" is 0, the function chooses the size).
41 ====================
42 */
43 snd_ringbuffer_t *Snd_CreateRingBuffer (const snd_format_t* format, unsigned int sampleframes, void* buffer)
44 {
45         snd_ringbuffer_t *ringbuffer;
46
47         // If the caller provides a buffer, it must give us its size
48         if (sampleframes == 0 && buffer != NULL)
49                 return NULL;
50
51         ringbuffer = (snd_ringbuffer_t*)Mem_Alloc(snd_mempool, sizeof (*ringbuffer));
52         memset(ringbuffer, 0, sizeof(*ringbuffer));
53         memcpy(&ringbuffer->format, format, sizeof(ringbuffer->format));
54
55         // If we haven't been given a buffer
56         if (buffer == NULL)
57         {
58                 unsigned int maxframes;
59                 size_t memsize;
60
61                 if (sampleframes == 0)
62                         maxframes = (format->speed + 1) / 2;  // Make the sound buffer large enough for containing 0.5 sec of sound
63                 else
64                         maxframes = sampleframes;
65
66                 memsize = maxframes * format->width * format->channels;
67                 ringbuffer->ring = (unsigned char *) Mem_Alloc(snd_mempool, memsize);
68                 ringbuffer->maxframes = maxframes;
69         }
70         else
71         {
72                 ringbuffer->ring = (unsigned char *) buffer;
73                 ringbuffer->maxframes = sampleframes;
74         }
75
76         return ringbuffer;
77 }
78
79
80 //=============================================================================
81
82 /*
83 ==============
84 S_LoadSound
85 ==============
86 */
87 qbool S_LoadSound (sfx_t *sfx, qbool complain)
88 {
89         char namebuffer[MAX_QPATH + 16];
90         size_t len;
91
92         // See if already loaded
93         if (sfx->fetcher != NULL)
94                 return true;
95
96         // If we weren't able to load it previously, no need to retry
97         // Note: S_PrecacheSound clears this flag to cause a retry
98         if (sfx->flags & SFXFLAG_FILEMISSING)
99                 return false;
100
101         // No sound?
102         if (snd_renderbuffer == NULL)
103                 return false;
104
105         // Initialize volume peak to 0; if ReplayGain is supported, the loader will change this away
106         sfx->volume_peak = 0.0;
107
108         if (developer_loading.integer)
109                 Con_Printf("loading sound %s\n", sfx->name);
110
111         SCR_PushLoadingScreen(sfx->name, 1);
112
113         // LadyHavoc: if the sound filename does not begin with sound/, try adding it
114         if (strncasecmp(sfx->name, "sound/", 6))
115         {
116                 dpsnprintf (namebuffer, sizeof(namebuffer), "sound/%s", sfx->name);
117                 len = strlen(namebuffer);
118                 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
119                 {
120                         if (S_LoadWavFile (namebuffer, sfx))
121                                 goto loaded;
122                         memcpy (namebuffer + len - 3, "ogg", 4);
123                 }
124                 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".ogg"))
125                 {
126                         if (OGG_LoadVorbisFile (namebuffer, sfx))
127                                 goto loaded;
128                 }
129 #ifdef USEXMP
130                 else if (len >= 1)
131                 {
132                         if (XMP_LoadModFile (namebuffer, sfx))
133                                 goto loaded;
134                 }
135 #endif
136         }
137
138         // LadyHavoc: then try without the added sound/ as wav and ogg
139         dpsnprintf (namebuffer, sizeof(namebuffer), "%s", sfx->name);
140         len = strlen(namebuffer);
141         // request foo.wav: tries foo.wav, then foo.ogg
142         // request foo.ogg: tries foo.ogg only
143         // request foo.mod: tries foo.mod only
144         if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
145         {
146                 if (S_LoadWavFile (namebuffer, sfx))
147                         goto loaded;
148                 memcpy (namebuffer + len - 3, "ogg", 4);
149         }
150         if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".ogg"))
151         {
152                 if (OGG_LoadVorbisFile (namebuffer, sfx))
153                         goto loaded;
154         }
155 #ifdef USEXMP
156         else if (len >= 1)
157         {
158                 if (XMP_LoadModFile (namebuffer, sfx))
159                         goto loaded;
160         }
161 #endif
162
163         // Can't load the sound!
164         sfx->flags |= SFXFLAG_FILEMISSING;
165         if (complain)
166                 Con_Printf(CON_ERROR "Failed to load sound \"%s\"\n", sfx->name);
167
168         SCR_PopLoadingScreen(false);
169         return false;
170
171 loaded:
172         SCR_PopLoadingScreen(false);
173         return true;
174 }