Skip to content

Commit 6397cc7

Browse files
authored
Integration of libsndfile to support SFX in various formats (#718)
* Convert audio format using SDL. * Remove padding, add padding for DMX format (thanks to Ceski). * Add precaching for non DMX sounds.
1 parent f63e4f0 commit 6397cc7

File tree

9 files changed

+344
-57
lines changed

9 files changed

+344
-57
lines changed

.github/workflows/continuous_integration.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ jobs:
9191
${{ matrix.config.msys-env }}-SDL2
9292
${{ matrix.config.msys-env }}-SDL2_image
9393
${{ matrix.config.msys-env }}-SDL2_mixer
94+
${{ matrix.config.msys-env }}-libsndfile
9495
${{ matrix.config.msys-env }}-libzip
9596
9697
- name: Install Dependencies (Linux)
@@ -113,6 +114,7 @@ jobs:
113114
libsdl2-image-dev \
114115
libsdl2-mixer-dev \
115116
libvorbis-dev \
117+
libsndfile1-dev \
116118
libzip-dev \
117119
zipcmp \
118120
zipmerge \
@@ -136,6 +138,7 @@ jobs:
136138
sdl2 \
137139
sdl2_image \
138140
sdl2_mixer \
141+
libsndfile \
139142
dylibbundler
140143
141144
- name: Generate vcpkg cache key

prboom2/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,16 @@ find_package(libzip REQUIRED)
8787
find_package(SDL2 2.0.7 REQUIRED)
8888
find_package(SDL2_mixer REQUIRED)
8989
find_package(ZLIB REQUIRED)
90+
find_package(SndFile 1.0.29 REQUIRED)
9091

9192
if(NOT TARGET SDL2_mixer::SDL2_mixer)
9293
add_library(SDL2_mixer::SDL2_mixer ALIAS SDL2_mixer::SDL2_mixer-static)
9394
endif()
9495

96+
if(SndFile_VERSION VERSION_GREATER_EQUAL "1.1.0")
97+
set(HAVE_SNDFILE_MPEG TRUE)
98+
endif()
99+
95100
if(WITH_IMAGE)
96101
find_package(SDL2_image)
97102
if(SDL2_image_FOUND)

prboom2/cmake/FindSndFile.cmake

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Variables defined:
2+
# SndFile_FOUND
3+
# SndFile_INCLUDE_DIR
4+
# SndFile_LIBRARY
5+
6+
find_package(PkgConfig QUIET)
7+
pkg_check_modules(PC_SndFile QUIET sndfile)
8+
9+
find_path(
10+
SndFile_INCLUDE_DIR sndfile.h
11+
HINTS "${PC_SndFile_INCLUDEDIR}"
12+
)
13+
14+
find_library(
15+
SndFile_LIBRARY
16+
NAMES sndfile libsndfile
17+
HINTS "${PC_SndFile_LIBDIR}"
18+
)
19+
20+
include(FindPackageHandleStandardArgs)
21+
find_package_handle_standard_args(
22+
SndFile
23+
REQUIRED_VARS SndFile_LIBRARY SndFile_INCLUDE_DIR
24+
VERSION_VAR SndFile_VERSION
25+
)
26+
27+
if(SndFile_FOUND)
28+
if(NOT TARGET SndFile::sndfile)
29+
add_library(SndFile::sndfile UNKNOWN IMPORTED)
30+
set_target_properties(
31+
SndFile::sndfile
32+
PROPERTIES IMPORTED_LOCATION "${SndFile_LIBRARY}"
33+
INTERFACE_INCLUDE_DIRECTORIES "${SndFile_INCLUDE_DIR}")
34+
endif()
35+
endif()
36+
37+
mark_as_advanced(SndFile_LIBRARY SndFile_INCLUDE_DIR)

prboom2/cmake/config.h.cin

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#cmakedefine HAVE_LIBVORBISFILE
3030
#cmakedefine HAVE_LIBPORTMIDI
3131
#cmakedefine HAVE_LIBOPENMPT
32+
#cmakedefine HAVE_SNDFILE_MPEG
3233

3334
#cmakedefine SIMPLECHECKS
3435

prboom2/src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ set(MUS2MID_SRC
446446
set(SDLDOOM_SOURCES
447447
SDL/i_main.c
448448
SDL/i_sound.c
449+
SDL/i_sndfile.c
450+
SDL/i_sndfile.h
449451
SDL/i_sshot.c
450452
SDL/i_system.c
451453
SDL/i_video.c
@@ -545,6 +547,7 @@ function(AddGameExecutable TARGET SOURCES)
545547
${SDL2_LIBRARIES}
546548
SDL2_mixer::SDL2_mixer
547549
ZLIB::ZLIB
550+
SndFile::sndfile
548551
)
549552

550553
if(WIN32)

prboom2/src/SDL/i_sndfile.c

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// Copyright (C) 2023 Fabian Greffrath
2+
//
3+
// This program is free software; you can redistribute it and/or
4+
// modify it under the terms of the GNU General Public License
5+
// as published by the Free Software Foundation; either version 2
6+
// of the License, or (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// DESCRIPTION:
14+
// Load sound lumps with libsndfile.
15+
16+
#include "SDL.h"
17+
#include "sndfile.h"
18+
19+
#include "lprintf.h"
20+
#include "memio.h"
21+
#include "z_zone.h"
22+
23+
static sf_count_t sfvio_get_filelen(void *user_data)
24+
{
25+
MEMFILE *fs = user_data;
26+
long pos;
27+
sf_count_t len;
28+
29+
pos = mem_ftell(fs);
30+
mem_fseek(fs, 0, MEM_SEEK_END);
31+
len = mem_ftell(fs);
32+
mem_fseek(fs, pos, MEM_SEEK_SET);
33+
34+
return len;
35+
}
36+
37+
static sf_count_t sfvio_seek(sf_count_t offset, int whence, void *user_data)
38+
{
39+
MEMFILE *fs = user_data;
40+
mem_fseek(fs, offset, whence);
41+
return mem_ftell(fs);
42+
}
43+
44+
static sf_count_t sfvio_read(void *ptr, sf_count_t count, void *user_data)
45+
{
46+
return mem_fread(ptr, 1, count, (MEMFILE *)user_data);
47+
}
48+
49+
static sf_count_t sfvio_tell(void *user_data)
50+
{
51+
return mem_ftell((MEMFILE *)user_data);
52+
}
53+
54+
void *Load_SNDFile(void *data, SDL_AudioSpec *sample, void **sampledata,
55+
Uint32 *samplelen)
56+
{
57+
SNDFILE *sndfile;
58+
SF_INFO sfinfo = {0};
59+
SF_VIRTUAL_IO sfvio =
60+
{
61+
sfvio_get_filelen,
62+
sfvio_seek,
63+
sfvio_read,
64+
NULL,
65+
sfvio_tell
66+
};
67+
Uint32 local_samplelen;
68+
void *local_sampledata;
69+
sf_count_t num_frames;
70+
dboolean float_format;
71+
72+
MEMFILE *sfdata = mem_fopen_read(data, *samplelen);
73+
74+
sndfile = sf_open_virtual(&sfvio, SFM_READ, &sfinfo, sfdata);
75+
76+
if (!sndfile)
77+
{
78+
lprintf(LO_WARN, "sf_open_virtual: %s\n", sf_strerror(sndfile));
79+
mem_fclose(sfdata);
80+
return NULL;
81+
}
82+
83+
if (sfinfo.frames <= 0 || sfinfo.channels <= 0)
84+
{
85+
sf_close(sndfile);
86+
mem_fclose(sfdata);
87+
return NULL;
88+
}
89+
90+
switch ((sfinfo.format & SF_FORMAT_SUBMASK))
91+
{
92+
case SF_FORMAT_PCM_24:
93+
case SF_FORMAT_PCM_32:
94+
case SF_FORMAT_FLOAT:
95+
case SF_FORMAT_DOUBLE:
96+
case SF_FORMAT_VORBIS:
97+
case SF_FORMAT_OPUS:
98+
case SF_FORMAT_ALAC_20:
99+
case SF_FORMAT_ALAC_24:
100+
case SF_FORMAT_ALAC_32:
101+
#ifdef HAVE_SNDFILE_MPEG
102+
case SF_FORMAT_MPEG_LAYER_I:
103+
case SF_FORMAT_MPEG_LAYER_II:
104+
case SF_FORMAT_MPEG_LAYER_III:
105+
#endif
106+
float_format = true;
107+
break;
108+
default:
109+
float_format = false;
110+
break;
111+
}
112+
113+
local_samplelen = sfinfo.frames * sfinfo.channels * (float_format ? sizeof(float) : sizeof(short));
114+
local_sampledata = Z_Malloc(local_samplelen);
115+
116+
if (float_format)
117+
{
118+
num_frames = sf_readf_float(sndfile, local_sampledata, sfinfo.frames);
119+
}
120+
else
121+
{
122+
num_frames = sf_readf_short(sndfile, local_sampledata, sfinfo.frames);
123+
}
124+
125+
if (num_frames < sfinfo.frames)
126+
{
127+
lprintf(LO_WARN, "sf_readf: %s\n", sf_strerror(sndfile));
128+
sf_close(sndfile);
129+
mem_fclose(sfdata);
130+
Z_Free(local_sampledata);
131+
return NULL;
132+
}
133+
134+
sf_close(sndfile);
135+
mem_fclose(sfdata);
136+
137+
sample->channels = sfinfo.channels;
138+
sample->freq = sfinfo.samplerate;
139+
sample->format = float_format ? AUDIO_F32 : AUDIO_S16;
140+
141+
*sampledata = local_sampledata;
142+
*samplelen = local_samplelen;
143+
144+
return sample;
145+
}

prboom2/src/SDL/i_sndfile.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (C) 2023 Fabian Greffrath
2+
//
3+
// This program is free software; you can redistribute it and/or
4+
// modify it under the terms of the GNU General Public License
5+
// as published by the Free Software Foundation; either version 2
6+
// of the License, or (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// DESCRIPTION:
14+
// Load sound lumps with libsndfile.
15+
16+
#ifndef I_SNDFILE_H
17+
#define I_SNDFILE_H
18+
19+
#include "SDL_audio.h"
20+
21+
void *Load_SNDFile(void *data, SDL_AudioSpec *sample, void **sampledata,
22+
Uint32 *samplelen);
23+
24+
#endif

0 commit comments

Comments
 (0)