diff --git a/CMakeLists.txt b/CMakeLists.txt index d7b25c5b8..744d80139 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,9 +197,9 @@ if( MSVC ) # Function-level linking # Disable run-time type information if ( HAVE_VULKAN ) - set( ALL_C_FLAGS "/GF /Gy /GR- /permissive- /DHAVE_VULKAN" ) + set( ALL_C_FLAGS "/GF /Gy /permissive- /DHAVE_VULKAN" ) else() - set( ALL_C_FLAGS "/GF /Gy /GR- /permissive-" ) + set( ALL_C_FLAGS "/GF /Gy /permissive-" ) endif() # Use SSE 2 as minimum always as the true color drawers needs it for __vectorcall @@ -241,7 +241,7 @@ if( MSVC ) # Most of these need to be cleaned out. The source is currently infested with far too much conditional compilation which is a constant source of problems. - set( ALL_C_FLAGS "${ALL_C_FLAGS} /DRENDERTYPESDL=1 /DMIXERTYPEWIN=1 /DSDL_USEFOLDER /DSDL_TARGET=2 /DUSE_OPENGL=1 /DSTARTUP_WINDOW /DUSE_LIBVPX /DHAVE_VORBIS /DHAVE_XMP /DNOASM=1 /DWIN32 /DLIBXMP_CORE_PLAYER" ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} /DRENDERTYPESDL=1 /DMIXERTYPEWIN=1 /DSDL_USEFOLDER /DSDL_TARGET=2 /DUSE_OPENGL=1 /DSTARTUP_WINDOW /DUSE_LIBVPX /DNOASM=1 /DWIN32" ) # The CMake configurations set /GR and /MD by default, which conflict with our settings. string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} ) diff --git a/platform/Windows/include/FLAC/all.h b/platform/Windows/include/FLAC/all.h deleted file mode 100644 index 9e288528b..000000000 --- a/platform/Windows/include/FLAC/all.h +++ /dev/null @@ -1,371 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__ALL_H -#define FLAC__ALL_H - -#include "export.h" - -#include "assert.h" -#include "callback.h" -#include "format.h" -#include "metadata.h" -#include "ordinals.h" -#include "stream_decoder.h" -#include "stream_encoder.h" - -/** \mainpage - * - * \section intro Introduction - * - * This is the documentation for the FLAC C and C++ APIs. It is - * highly interconnected; this introduction should give you a top - * level idea of the structure and how to find the information you - * need. As a prerequisite you should have at least a basic - * knowledge of the FLAC format, documented - * here. - * - * \section c_api FLAC C API - * - * The FLAC C API is the interface to libFLAC, a set of structures - * describing the components of FLAC streams, and functions for - * encoding and decoding streams, as well as manipulating FLAC - * metadata in files. The public include files will be installed - * in your include area (for example /usr/include/FLAC/...). - * - * By writing a little code and linking against libFLAC, it is - * relatively easy to add FLAC support to another program. The - * library is licensed under Xiph's BSD license. - * Complete source code of libFLAC as well as the command-line - * encoder and plugins is available and is a useful source of - * examples. - * - * Aside from encoders and decoders, libFLAC provides a powerful - * metadata interface for manipulating metadata in FLAC files. It - * allows the user to add, delete, and modify FLAC metadata blocks - * and it can automatically take advantage of PADDING blocks to avoid - * rewriting the entire FLAC file when changing the size of the - * metadata. - * - * libFLAC usually only requires the standard C library and C math - * library. In particular, threading is not used so there is no - * dependency on a thread library. However, libFLAC does not use - * global variables and should be thread-safe. - * - * libFLAC also supports encoding to and decoding from Ogg FLAC. - * However the metadata editing interfaces currently have limited - * read-only support for Ogg FLAC files. - * - * \section cpp_api FLAC C++ API - * - * The FLAC C++ API is a set of classes that encapsulate the - * structures and functions in libFLAC. They provide slightly more - * functionality with respect to metadata but are otherwise - * equivalent. For the most part, they share the same usage as - * their counterparts in libFLAC, and the FLAC C API documentation - * can be used as a supplement. The public include files - * for the C++ API will be installed in your include area (for - * example /usr/include/FLAC++/...). - * - * libFLAC++ is also licensed under - * Xiph's BSD license. - * - * \section getting_started Getting Started - * - * A good starting point for learning the API is to browse through - * the modules. Modules are logical - * groupings of related functions or classes, which correspond roughly - * to header files or sections of header files. Each module includes a - * detailed description of the general usage of its functions or - * classes. - * - * From there you can go on to look at the documentation of - * individual functions. You can see different views of the individual - * functions through the links in top bar across this page. - * - * If you prefer a more hands-on approach, you can jump right to some - * example code. - * - * \section porting_guide Porting Guide - * - * Starting with FLAC 1.1.3 a \link porting Porting Guide \endlink - * has been introduced which gives detailed instructions on how to - * port your code to newer versions of FLAC. - * - * \section embedded_developers Embedded Developers - * - * libFLAC has grown larger over time as more functionality has been - * included, but much of it may be unnecessary for a particular embedded - * implementation. Unused parts may be pruned by some simple editing of - * src/libFLAC/Makefile.am. In general, the decoders, encoders, and - * metadata interface are all independent from each other. - * - * It is easiest to just describe the dependencies: - * - * - All modules depend on the \link flac_format Format \endlink module. - * - The decoders and encoders depend on the bitbuffer. - * - The decoder is independent of the encoder. The encoder uses the - * decoder because of the verify feature, but this can be removed if - * not needed. - * - Parts of the metadata interface require the stream decoder (but not - * the encoder). - * - Ogg support is selectable through the compile time macro - * \c FLAC__HAS_OGG. - * - * For example, if your application only requires the stream decoder, no - * encoder, and no metadata interface, you can remove the stream encoder - * and the metadata interface, which will greatly reduce the size of the - * library. - * - * Also, there are several places in the libFLAC code with comments marked - * with "OPT:" where a #define can be changed to enable code that might be - * faster on a specific platform. Experimenting with these can yield faster - * binaries. - */ - -/** \defgroup porting Porting Guide for New Versions - * - * This module describes differences in the library interfaces from - * version to version. It assists in the porting of code that uses - * the libraries to newer versions of FLAC. - * - * One simple facility for making porting easier that has been added - * in FLAC 1.1.3 is a set of \c #defines in \c export.h of each - * library's includes (e.g. \c include/FLAC/export.h). The - * \c #defines mirror the libraries' - * libtool version numbers, - * e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT, - * \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE. - * These can be used to support multiple versions of an API during the - * transition phase, e.g. - * - * \code - * #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 - * legacy code - * #else - * new code - * #endif - * \endcode - * - * The the source will work for multiple versions and the legacy code can - * easily be removed when the transition is complete. - * - * Another available symbol is FLAC_API_SUPPORTS_OGG_FLAC (defined in - * include/FLAC/export.h), which can be used to determine whether or not - * the library has been compiled with support for Ogg FLAC. This is - * simpler than trying to call an Ogg init function and catching the - * error. - */ - -/** \defgroup porting_1_1_2_to_1_1_3 Porting from FLAC 1.1.2 to 1.1.3 - * \ingroup porting - * - * \brief - * This module describes porting from FLAC 1.1.2 to FLAC 1.1.3. - * - * The main change between the APIs in 1.1.2 and 1.1.3 is that they have - * been simplified. First, libOggFLAC has been merged into libFLAC and - * libOggFLAC++ has been merged into libFLAC++. Second, both the three - * decoding layers and three encoding layers have been merged into a - * single stream decoder and stream encoder. That is, the functionality - * of FLAC__SeekableStreamDecoder and FLAC__FileDecoder has been merged - * into FLAC__StreamDecoder, and FLAC__SeekableStreamEncoder and - * FLAC__FileEncoder into FLAC__StreamEncoder. Only the - * FLAC__StreamDecoder and FLAC__StreamEncoder remain. What this means - * is there is now a single API that can be used to encode or decode - * streams to/from native FLAC or Ogg FLAC and the single API can work - * on both seekable and non-seekable streams. - * - * Instead of creating an encoder or decoder of a certain layer, now the - * client will always create a FLAC__StreamEncoder or - * FLAC__StreamDecoder. The old layers are now differentiated by the - * initialization function. For example, for the decoder, - * FLAC__stream_decoder_init() has been replaced by - * FLAC__stream_decoder_init_stream(). This init function takes - * callbacks for the I/O, and the seeking callbacks are optional. This - * allows the client to use the same object for seekable and - * non-seekable streams. For decoding a FLAC file directly, the client - * can use FLAC__stream_decoder_init_file() and pass just a filename - * and fewer callbacks; most of the other callbacks are supplied - * internally. For situations where fopen()ing by filename is not - * possible (e.g. Unicode filenames on Windows) the client can instead - * open the file itself and supply the FILE* to - * FLAC__stream_decoder_init_FILE(). The init functions now returns a - * FLAC__StreamDecoderInitStatus instead of FLAC__StreamDecoderState. - * Since the callbacks and client data are now passed to the init - * function, the FLAC__stream_decoder_set_*_callback() functions and - * FLAC__stream_decoder_set_client_data() are no longer needed. The - * rest of the calls to the decoder are the same as before. - * - * There are counterpart init functions for Ogg FLAC, e.g. - * FLAC__stream_decoder_init_ogg_stream(). All the rest of the calls - * and callbacks are the same as for native FLAC. - * - * As an example, in FLAC 1.1.2 a seekable stream decoder would have - * been set up like so: - * - * \code - * FLAC__SeekableStreamDecoder *decoder = FLAC__seekable_stream_decoder_new(); - * if(decoder == NULL) do_something; - * FLAC__seekable_stream_decoder_set_md5_checking(decoder, true); - * [... other settings ...] - * FLAC__seekable_stream_decoder_set_read_callback(decoder, my_read_callback); - * FLAC__seekable_stream_decoder_set_seek_callback(decoder, my_seek_callback); - * FLAC__seekable_stream_decoder_set_tell_callback(decoder, my_tell_callback); - * FLAC__seekable_stream_decoder_set_length_callback(decoder, my_length_callback); - * FLAC__seekable_stream_decoder_set_eof_callback(decoder, my_eof_callback); - * FLAC__seekable_stream_decoder_set_write_callback(decoder, my_write_callback); - * FLAC__seekable_stream_decoder_set_metadata_callback(decoder, my_metadata_callback); - * FLAC__seekable_stream_decoder_set_error_callback(decoder, my_error_callback); - * FLAC__seekable_stream_decoder_set_client_data(decoder, my_client_data); - * if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) do_something; - * \endcode - * - * In FLAC 1.1.3 it is like this: - * - * \code - * FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new(); - * if(decoder == NULL) do_something; - * FLAC__stream_decoder_set_md5_checking(decoder, true); - * [... other settings ...] - * if(FLAC__stream_decoder_init_stream( - * decoder, - * my_read_callback, - * my_seek_callback, // or NULL - * my_tell_callback, // or NULL - * my_length_callback, // or NULL - * my_eof_callback, // or NULL - * my_write_callback, - * my_metadata_callback, // or NULL - * my_error_callback, - * my_client_data - * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; - * \endcode - * - * or you could do; - * - * \code - * [...] - * FILE *file = fopen("somefile.flac","rb"); - * if(file == NULL) do_somthing; - * if(FLAC__stream_decoder_init_FILE( - * decoder, - * file, - * my_write_callback, - * my_metadata_callback, // or NULL - * my_error_callback, - * my_client_data - * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; - * \endcode - * - * or just: - * - * \code - * [...] - * if(FLAC__stream_decoder_init_file( - * decoder, - * "somefile.flac", - * my_write_callback, - * my_metadata_callback, // or NULL - * my_error_callback, - * my_client_data - * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; - * \endcode - * - * Another small change to the decoder is in how it handles unparseable - * streams. Before, when the decoder found an unparseable stream - * (reserved for when the decoder encounters a stream from a future - * encoder that it can't parse), it changed the state to - * \c FLAC__STREAM_DECODER_UNPARSEABLE_STREAM. Now the decoder instead - * drops sync and calls the error callback with a new error code - * \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM. This is - * more robust. If your error callback does not discriminate on the the - * error state, your code does not need to be changed. - * - * The encoder now has a new setting: - * FLAC__stream_encoder_set_apodization(). This is for setting the - * method used to window the data before LPC analysis. You only need to - * add a call to this function if the default is not suitable. There - * are also two new convenience functions that may be useful: - * FLAC__metadata_object_cuesheet_calculate_cddb_id() and - * FLAC__metadata_get_cuesheet(). - * - * The \a bytes parameter to FLAC__StreamDecoderReadCallback, - * FLAC__StreamEncoderReadCallback, and FLAC__StreamEncoderWriteCallback - * is now \c size_t instead of \c unsigned. - */ - -/** \defgroup porting_1_1_3_to_1_1_4 Porting from FLAC 1.1.3 to 1.1.4 - * \ingroup porting - * - * \brief - * This module describes porting from FLAC 1.1.3 to FLAC 1.1.4. - * - * There were no changes to any of the interfaces from 1.1.3 to 1.1.4. - * There was a slight change in the implementation of - * FLAC__stream_encoder_set_metadata(); the function now makes a copy - * of the \a metadata array of pointers so the client no longer needs - * to maintain it after the call. The objects themselves that are - * pointed to by the array are still not copied though and must be - * maintained until the call to FLAC__stream_encoder_finish(). - */ - -/** \defgroup porting_1_1_4_to_1_2_0 Porting from FLAC 1.1.4 to 1.2.0 - * \ingroup porting - * - * \brief - * This module describes porting from FLAC 1.1.4 to FLAC 1.2.0. - * - * There were only very minor changes to the interfaces from 1.1.4 to 1.2.0. - * In libFLAC, \c FLAC__format_sample_rate_is_subset() was added. - * In libFLAC++, \c FLAC::Decoder::Stream::get_decode_position() was added. - * - * Finally, value of the constant \c FLAC__FRAME_HEADER_RESERVED_LEN - * has changed to reflect the conversion of one of the reserved bits - * into active use. It used to be \c 2 and now is \c 1. However the - * FLAC frame header length has not changed, so to skip the proper - * number of bits, use \c FLAC__FRAME_HEADER_RESERVED_LEN + - * \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN - */ - -/** \defgroup flac FLAC C API - * - * The FLAC C API is the interface to libFLAC, a set of structures - * describing the components of FLAC streams, and functions for - * encoding and decoding streams, as well as manipulating FLAC - * metadata in files. - * - * You should start with the format components as all other modules - * are dependent on it. - */ - -#endif diff --git a/platform/Windows/include/FLAC/assert.h b/platform/Windows/include/FLAC/assert.h deleted file mode 100644 index 787cea913..000000000 --- a/platform/Windows/include/FLAC/assert.h +++ /dev/null @@ -1,46 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__ASSERT_H -#define FLAC__ASSERT_H - -/* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */ -#ifdef DEBUG -#include -#define FLAC__ASSERT(x) assert(x) -#define FLAC__ASSERT_DECLARATION(x) x -#else -#define FLAC__ASSERT(x) -#define FLAC__ASSERT_DECLARATION(x) -#endif - -#endif diff --git a/platform/Windows/include/FLAC/callback.h b/platform/Windows/include/FLAC/callback.h deleted file mode 100644 index 71bbaec6d..000000000 --- a/platform/Windows/include/FLAC/callback.h +++ /dev/null @@ -1,185 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__CALLBACK_H -#define FLAC__CALLBACK_H - -#include "ordinals.h" -#include /* for size_t */ - -/** \file include/FLAC/callback.h - * - * \brief - * This module defines the structures for describing I/O callbacks - * to the other FLAC interfaces. - * - * See the detailed documentation for callbacks in the - * \link flac_callbacks callbacks \endlink module. - */ - -/** \defgroup flac_callbacks FLAC/callback.h: I/O callback structures - * \ingroup flac - * - * \brief - * This module defines the structures for describing I/O callbacks - * to the other FLAC interfaces. - * - * The purpose of the I/O callback functions is to create a common way - * for the metadata interfaces to handle I/O. - * - * Originally the metadata interfaces required filenames as the way of - * specifying FLAC files to operate on. This is problematic in some - * environments so there is an additional option to specify a set of - * callbacks for doing I/O on the FLAC file, instead of the filename. - * - * In addition to the callbacks, a FLAC__IOHandle type is defined as an - * opaque structure for a data source. - * - * The callback function prototypes are similar (but not identical) to the - * stdio functions fread, fwrite, fseek, ftell, feof, and fclose. If you use - * stdio streams to implement the callbacks, you can pass fread, fwrite, and - * fclose anywhere a FLAC__IOCallback_Read, FLAC__IOCallback_Write, or - * FLAC__IOCallback_Close is required, and a FILE* anywhere a FLAC__IOHandle - * is required. \warning You generally CANNOT directly use fseek or ftell - * for FLAC__IOCallback_Seek or FLAC__IOCallback_Tell since on most systems - * these use 32-bit offsets and FLAC requires 64-bit offsets to deal with - * large files. You will have to find an equivalent function (e.g. ftello), - * or write a wrapper. The same is true for feof() since this is usually - * implemented as a macro, not as a function whose address can be taken. - * - * \{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** This is the opaque handle type used by the callbacks. Typically - * this is a \c FILE* or address of a file descriptor. - */ -typedef void* FLAC__IOHandle; - -/** Signature for the read callback. - * The signature and semantics match POSIX fread() implementations - * and can generally be used interchangeably. - * - * \param ptr The address of the read buffer. - * \param size The size of the records to be read. - * \param nmemb The number of records to be read. - * \param handle The handle to the data source. - * \retval size_t - * The number of records read. - */ -typedef size_t (*FLAC__IOCallback_Read) (void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle); - -/** Signature for the write callback. - * The signature and semantics match POSIX fwrite() implementations - * and can generally be used interchangeably. - * - * \param ptr The address of the write buffer. - * \param size The size of the records to be written. - * \param nmemb The number of records to be written. - * \param handle The handle to the data source. - * \retval size_t - * The number of records written. - */ -typedef size_t (*FLAC__IOCallback_Write) (const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle); - -/** Signature for the seek callback. - * The signature and semantics mostly match POSIX fseek() WITH ONE IMPORTANT - * EXCEPTION: the offset is a 64-bit type whereas fseek() is generally 'long' - * and 32-bits wide. - * - * \param handle The handle to the data source. - * \param offset The new position, relative to \a whence - * \param whence \c SEEK_SET, \c SEEK_CUR, or \c SEEK_END - * \retval int - * \c 0 on success, \c -1 on error. - */ -typedef int (*FLAC__IOCallback_Seek) (FLAC__IOHandle handle, FLAC__int64 offset, int whence); - -/** Signature for the tell callback. - * The signature and semantics mostly match POSIX ftell() WITH ONE IMPORTANT - * EXCEPTION: the offset is a 64-bit type whereas ftell() is generally 'long' - * and 32-bits wide. - * - * \param handle The handle to the data source. - * \retval FLAC__int64 - * The current position on success, \c -1 on error. - */ -typedef FLAC__int64 (*FLAC__IOCallback_Tell) (FLAC__IOHandle handle); - -/** Signature for the EOF callback. - * The signature and semantics mostly match POSIX feof() but WATCHOUT: - * on many systems, feof() is a macro, so in this case a wrapper function - * must be provided instead. - * - * \param handle The handle to the data source. - * \retval int - * \c 0 if not at end of file, nonzero if at end of file. - */ -typedef int (*FLAC__IOCallback_Eof) (FLAC__IOHandle handle); - -/** Signature for the close callback. - * The signature and semantics match POSIX fclose() implementations - * and can generally be used interchangeably. - * - * \param handle The handle to the data source. - * \retval int - * \c 0 on success, \c EOF on error. - */ -typedef int (*FLAC__IOCallback_Close) (FLAC__IOHandle handle); - -/** A structure for holding a set of callbacks. - * Each FLAC interface that requires a FLAC__IOCallbacks structure will - * describe which of the callbacks are required. The ones that are not - * required may be set to NULL. - * - * If the seek requirement for an interface is optional, you can signify that - * a data sorce is not seekable by setting the \a seek field to \c NULL. - */ -typedef struct { - FLAC__IOCallback_Read read; - FLAC__IOCallback_Write write; - FLAC__IOCallback_Seek seek; - FLAC__IOCallback_Tell tell; - FLAC__IOCallback_Eof eof; - FLAC__IOCallback_Close close; -} FLAC__IOCallbacks; - -/* \} */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/Windows/include/FLAC/export.h b/platform/Windows/include/FLAC/export.h deleted file mode 100644 index 2232b410b..000000000 --- a/platform/Windows/include/FLAC/export.h +++ /dev/null @@ -1,97 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__EXPORT_H -#define FLAC__EXPORT_H - -/** \file include/FLAC/export.h - * - * \brief - * This module contains #defines and symbols for exporting function - * calls, and providing version information and compiled-in features. - * - * See the \link flac_export export \endlink module. - */ - -/** \defgroup flac_export FLAC/export.h: export symbols - * \ingroup flac - * - * \brief - * This module contains #defines and symbols for exporting function - * calls, and providing version information and compiled-in features. - * - * If you are compiling with MSVC and will link to the static library - * (libFLAC.lib) you should define FLAC__NO_DLL in your project to - * make sure the symbols are exported properly. - * - * \{ - */ - -#if defined(FLAC__NO_DLL) -#define FLAC_API - -#elif defined(_MSC_VER) -#ifdef FLAC_API_EXPORTS -#define FLAC_API _declspec(dllexport) -#else -#define FLAC_API _declspec(dllimport) -#endif - -#elif defined(FLAC__USE_VISIBILITY_ATTR) -#define FLAC_API __attribute__ ((visibility ("default"))) - -#else -#define FLAC_API - -#endif - -/** These #defines will mirror the libtool-based library version number, see - * http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning - */ -#define FLAC_API_VERSION_CURRENT 11 -#define FLAC_API_VERSION_REVISION 0 /**< see above */ -#define FLAC_API_VERSION_AGE 3 /**< see above */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** \c 1 if the library has been compiled with support for Ogg FLAC, else \c 0. */ -extern FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC; - -#ifdef __cplusplus -} -#endif - -/* \} */ - -#endif diff --git a/platform/Windows/include/FLAC/format.h b/platform/Windows/include/FLAC/format.h deleted file mode 100644 index e4c1c1a61..000000000 --- a/platform/Windows/include/FLAC/format.h +++ /dev/null @@ -1,1023 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__FORMAT_H -#define FLAC__FORMAT_H - -#include "export.h" -#include "ordinals.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file include/FLAC/format.h - * - * \brief - * This module contains structure definitions for the representation - * of FLAC format components in memory. These are the basic - * structures used by the rest of the interfaces. - * - * See the detailed documentation in the - * \link flac_format format \endlink module. - */ - -/** \defgroup flac_format FLAC/format.h: format components - * \ingroup flac - * - * \brief - * This module contains structure definitions for the representation - * of FLAC format components in memory. These are the basic - * structures used by the rest of the interfaces. - * - * First, you should be familiar with the - * FLAC format. Many of the values here - * follow directly from the specification. As a user of libFLAC, the - * interesting parts really are the structures that describe the frame - * header and metadata blocks. - * - * The format structures here are very primitive, designed to store - * information in an efficient way. Reading information from the - * structures is easy but creating or modifying them directly is - * more complex. For the most part, as a user of a library, editing - * is not necessary; however, for metadata blocks it is, so there are - * convenience functions provided in the \link flac_metadata metadata - * module \endlink to simplify the manipulation of metadata blocks. - * - * \note - * It's not the best convention, but symbols ending in _LEN are in bits - * and _LENGTH are in bytes. _LENGTH symbols are \#defines instead of - * global variables because they are usually used when declaring byte - * arrays and some compilers require compile-time knowledge of array - * sizes when declared on the stack. - * - * \{ - */ - - -/* - Most of the values described in this file are defined by the FLAC - format specification. There is nothing to tune here. -*/ - -/** The largest legal metadata type code. */ -#define FLAC__MAX_METADATA_TYPE_CODE (126u) - -/** The minimum block size, in samples, permitted by the format. */ -#define FLAC__MIN_BLOCK_SIZE (16u) - -/** The maximum block size, in samples, permitted by the format. */ -#define FLAC__MAX_BLOCK_SIZE (65535u) - -/** The maximum block size, in samples, permitted by the FLAC subset for - * sample rates up to 48kHz. */ -#define FLAC__SUBSET_MAX_BLOCK_SIZE_48000HZ (4608u) - -/** The maximum number of channels permitted by the format. */ -#define FLAC__MAX_CHANNELS (8u) - -/** The minimum sample resolution permitted by the format. */ -#define FLAC__MIN_BITS_PER_SAMPLE (4u) - -/** The maximum sample resolution permitted by the format. */ -#define FLAC__MAX_BITS_PER_SAMPLE (32u) - -/** The maximum sample resolution permitted by libFLAC. - * - * \warning - * FLAC__MAX_BITS_PER_SAMPLE is the limit of the FLAC format. However, - * the reference encoder/decoder is currently limited to 24 bits because - * of prevalent 32-bit math, so make sure and use this value when - * appropriate. - */ -#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (24u) - -/** The maximum sample rate permitted by the format. The value is - * ((2 ^ 16) - 1) * 10; see FLAC format - * as to why. - */ -#define FLAC__MAX_SAMPLE_RATE (655350u) - -/** The maximum LPC order permitted by the format. */ -#define FLAC__MAX_LPC_ORDER (32u) - -/** The maximum LPC order permitted by the FLAC subset for sample rates - * up to 48kHz. */ -#define FLAC__SUBSET_MAX_LPC_ORDER_48000HZ (12u) - -/** The minimum quantized linear predictor coefficient precision - * permitted by the format. - */ -#define FLAC__MIN_QLP_COEFF_PRECISION (5u) - -/** The maximum quantized linear predictor coefficient precision - * permitted by the format. - */ -#define FLAC__MAX_QLP_COEFF_PRECISION (15u) - -/** The maximum order of the fixed predictors permitted by the format. */ -#define FLAC__MAX_FIXED_ORDER (4u) - -/** The maximum Rice partition order permitted by the format. */ -#define FLAC__MAX_RICE_PARTITION_ORDER (15u) - -/** The maximum Rice partition order permitted by the FLAC Subset. */ -#define FLAC__SUBSET_MAX_RICE_PARTITION_ORDER (8u) - -/** The version string of the release, stamped onto the libraries and binaries. - * - * \note - * This does not correspond to the shared library version number, which - * is used to determine binary compatibility. - */ -extern FLAC_API const char *FLAC__VERSION_STRING; - -/** The vendor string inserted by the encoder into the VORBIS_COMMENT block. - * This is a NUL-terminated ASCII string; when inserted into the - * VORBIS_COMMENT the trailing null is stripped. - */ -extern FLAC_API const char *FLAC__VENDOR_STRING; - -/** The byte string representation of the beginning of a FLAC stream. */ -extern FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */ - -/** The 32-bit integer big-endian representation of the beginning of - * a FLAC stream. - */ -extern FLAC_API const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */ - -/** The length of the FLAC signature in bits. */ -extern FLAC_API const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */ - -/** The length of the FLAC signature in bytes. */ -#define FLAC__STREAM_SYNC_LENGTH (4u) - - -/***************************************************************************** - * - * Subframe structures - * - *****************************************************************************/ - -/*****************************************************************************/ - -/** An enumeration of the available entropy coding methods. */ -typedef enum { - FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE = 0, - /**< Residual is coded by partitioning into contexts, each with it's own - * 4-bit Rice parameter. */ - - FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 = 1 - /**< Residual is coded by partitioning into contexts, each with it's own - * 5-bit Rice parameter. */ -} FLAC__EntropyCodingMethodType; - -/** Maps a FLAC__EntropyCodingMethodType to a C string. - * - * Using a FLAC__EntropyCodingMethodType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[]; - - -/** Contents of a Rice partitioned residual - */ -typedef struct { - - unsigned *parameters; - /**< The Rice parameters for each context. */ - - unsigned *raw_bits; - /**< Widths for escape-coded partitions. Will be non-zero for escaped - * partitions and zero for unescaped partitions. - */ - - unsigned capacity_by_order; - /**< The capacity of the \a parameters and \a raw_bits arrays - * specified as an order, i.e. the number of array elements - * allocated is 2 ^ \a capacity_by_order. - */ -} FLAC__EntropyCodingMethod_PartitionedRiceContents; - -/** Header for a Rice partitioned residual. (c.f. format specification) - */ -typedef struct { - - unsigned order; - /**< The partition order, i.e. # of contexts = 2 ^ \a order. */ - - const FLAC__EntropyCodingMethod_PartitionedRiceContents *contents; - /**< The context's Rice parameters and/or raw bits. */ - -} FLAC__EntropyCodingMethod_PartitionedRice; - -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN; /**< == 5 (bits) */ -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */ - -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; -/**< == (1<format specification) - */ -typedef struct { - FLAC__EntropyCodingMethodType type; - union { - FLAC__EntropyCodingMethod_PartitionedRice partitioned_rice; - } data; -} FLAC__EntropyCodingMethod; - -extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */ - -/*****************************************************************************/ - -/** An enumeration of the available subframe types. */ -typedef enum { - FLAC__SUBFRAME_TYPE_CONSTANT = 0, /**< constant signal */ - FLAC__SUBFRAME_TYPE_VERBATIM = 1, /**< uncompressed signal */ - FLAC__SUBFRAME_TYPE_FIXED = 2, /**< fixed polynomial prediction */ - FLAC__SUBFRAME_TYPE_LPC = 3 /**< linear prediction */ -} FLAC__SubframeType; - -/** Maps a FLAC__SubframeType to a C string. - * - * Using a FLAC__SubframeType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__SubframeTypeString[]; - - -/** CONSTANT subframe. (c.f. format specification) - */ -typedef struct { - FLAC__int32 value; /**< The constant signal value. */ -} FLAC__Subframe_Constant; - - -/** VERBATIM subframe. (c.f. format specification) - */ -typedef struct { - const FLAC__int32 *data; /**< A pointer to verbatim signal. */ -} FLAC__Subframe_Verbatim; - - -/** FIXED subframe. (c.f. format specification) - */ -typedef struct { - FLAC__EntropyCodingMethod entropy_coding_method; - /**< The residual coding method. */ - - unsigned order; - /**< The polynomial order. */ - - FLAC__int32 warmup[FLAC__MAX_FIXED_ORDER]; - /**< Warmup samples to prime the predictor, length == order. */ - - const FLAC__int32 *residual; - /**< The residual signal, length == (blocksize minus order) samples. */ -} FLAC__Subframe_Fixed; - - -/** LPC subframe. (c.f. format specification) - */ -typedef struct { - FLAC__EntropyCodingMethod entropy_coding_method; - /**< The residual coding method. */ - - unsigned order; - /**< The FIR order. */ - - unsigned qlp_coeff_precision; - /**< Quantized FIR filter coefficient precision in bits. */ - - int quantization_level; - /**< The qlp coeff shift needed. */ - - FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; - /**< FIR filter coefficients. */ - - FLAC__int32 warmup[FLAC__MAX_LPC_ORDER]; - /**< Warmup samples to prime the predictor, length == order. */ - - const FLAC__int32 *residual; - /**< The residual signal, length == (blocksize minus order) samples. */ -} FLAC__Subframe_LPC; - -extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */ - - -/** FLAC subframe structure. (c.f. format specification) - */ -typedef struct { - FLAC__SubframeType type; - union { - FLAC__Subframe_Constant constant; - FLAC__Subframe_Fixed fixed; - FLAC__Subframe_LPC lpc; - FLAC__Subframe_Verbatim verbatim; - } data; - unsigned wasted_bits; -} FLAC__Subframe; - -/** == 1 (bit) - * - * This used to be a zero-padding bit (hence the name - * FLAC__SUBFRAME_ZERO_PAD_LEN) but is now a reserved bit. It still has a - * mandatory value of \c 0 but in the future may take on the value \c 0 or \c 1 - * to mean something else. - */ -extern FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN; -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */ -extern FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */ - -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK; /**< = 0x00 */ -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; /**< = 0x02 */ -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /**< = 0x10 */ -extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /**< = 0x40 */ - -/*****************************************************************************/ - - -/***************************************************************************** - * - * Frame structures - * - *****************************************************************************/ - -/** An enumeration of the available channel assignments. */ -typedef enum { - FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT = 0, /**< independent channels */ - FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE = 1, /**< left+side stereo */ - FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE = 2, /**< right+side stereo */ - FLAC__CHANNEL_ASSIGNMENT_MID_SIDE = 3 /**< mid+side stereo */ -} FLAC__ChannelAssignment; - -/** Maps a FLAC__ChannelAssignment to a C string. - * - * Using a FLAC__ChannelAssignment as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__ChannelAssignmentString[]; - -/** An enumeration of the possible frame numbering methods. */ -typedef enum { - FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER, /**< number contains the frame number */ - FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER /**< number contains the sample number of first sample in frame */ -} FLAC__FrameNumberType; - -/** Maps a FLAC__FrameNumberType to a C string. - * - * Using a FLAC__FrameNumberType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__FrameNumberTypeString[]; - - -/** FLAC frame header structure. (c.f. format specification) - */ -typedef struct { - unsigned blocksize; - /**< The number of samples per subframe. */ - - unsigned sample_rate; - /**< The sample rate in Hz. */ - - unsigned channels; - /**< The number of channels (== number of subframes). */ - - FLAC__ChannelAssignment channel_assignment; - /**< The channel assignment for the frame. */ - - unsigned bits_per_sample; - /**< The sample resolution. */ - - FLAC__FrameNumberType number_type; - /**< The numbering scheme used for the frame. As a convenience, the - * decoder will always convert a frame number to a sample number because - * the rules are complex. */ - - union { - FLAC__uint32 frame_number; - FLAC__uint64 sample_number; - } number; - /**< The frame number or sample number of first sample in frame; - * use the \a number_type value to determine which to use. */ - - FLAC__uint8 crc; - /**< CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) - * of the raw frame header bytes, meaning everything before the CRC byte - * including the sync code. - */ -} FLAC__FrameHeader; - -extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN; /**< == 14 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN; /**< == 1 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN; /**< == 1 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /**< == 4 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 (bits) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */ - - -/** FLAC frame footer structure. (c.f. format specification) - */ -typedef struct { - FLAC__uint16 crc; - /**< CRC-16 (polynomial = x^16 + x^15 + x^2 + x^0, initialized with - * 0) of the bytes before the crc, back to and including the frame header - * sync code. - */ -} FLAC__FrameFooter; - -extern FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */ - - -/** FLAC frame structure. (c.f. format specification) - */ -typedef struct { - FLAC__FrameHeader header; - FLAC__Subframe subframes[FLAC__MAX_CHANNELS]; - FLAC__FrameFooter footer; -} FLAC__Frame; - -/*****************************************************************************/ - - -/***************************************************************************** - * - * Meta-data structures - * - *****************************************************************************/ - -/** An enumeration of the available metadata block types. */ -typedef enum { - - FLAC__METADATA_TYPE_STREAMINFO = 0, - /**< STREAMINFO block */ - - FLAC__METADATA_TYPE_PADDING = 1, - /**< PADDING block */ - - FLAC__METADATA_TYPE_APPLICATION = 2, - /**< APPLICATION block */ - - FLAC__METADATA_TYPE_SEEKTABLE = 3, - /**< SEEKTABLE block */ - - FLAC__METADATA_TYPE_VORBIS_COMMENT = 4, - /**< VORBISCOMMENT block (a.k.a. FLAC tags) */ - - FLAC__METADATA_TYPE_CUESHEET = 5, - /**< CUESHEET block */ - - FLAC__METADATA_TYPE_PICTURE = 6, - /**< PICTURE block */ - - FLAC__METADATA_TYPE_UNDEFINED = 7 - /**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */ - -} FLAC__MetadataType; - -/** Maps a FLAC__MetadataType to a C string. - * - * Using a FLAC__MetadataType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__MetadataTypeString[]; - - -/** FLAC STREAMINFO structure. (c.f. format specification) - */ -typedef struct { - unsigned min_blocksize, max_blocksize; - unsigned min_framesize, max_framesize; - unsigned sample_rate; - unsigned channels; - unsigned bits_per_sample; - FLAC__uint64 total_samples; - FLAC__byte md5sum[16]; -} FLAC__StreamMetadata_StreamInfo; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; /**< == 16 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; /**< == 16 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; /**< == 24 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; /**< == 24 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; /**< == 20 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; /**< == 3 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; /**< == 5 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */ - -/** The total stream length of the STREAMINFO block in bytes. */ -#define FLAC__STREAM_METADATA_STREAMINFO_LENGTH (34u) - -/** FLAC PADDING structure. (c.f. format specification) - */ -typedef struct { - int dummy; - /**< Conceptually this is an empty struct since we don't store the - * padding bytes. Empty structs are not allowed by some C compilers, - * hence the dummy. - */ -} FLAC__StreamMetadata_Padding; - - -/** FLAC APPLICATION structure. (c.f. format specification) - */ -typedef struct { - FLAC__byte id[4]; - FLAC__byte *data; -} FLAC__StreamMetadata_Application; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */ - -/** SeekPoint structure used in SEEKTABLE blocks. (c.f. format specification) - */ -typedef struct { - FLAC__uint64 sample_number; - /**< The sample number of the target frame. */ - - FLAC__uint64 stream_offset; - /**< The offset, in bytes, of the target frame with respect to - * beginning of the first frame. */ - - unsigned frame_samples; - /**< The number of samples in the target frame. */ -} FLAC__StreamMetadata_SeekPoint; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */ - -/** The total stream length of a seek point in bytes. */ -#define FLAC__STREAM_METADATA_SEEKPOINT_LENGTH (18u) - -/** The value used in the \a sample_number field of - * FLAC__StreamMetadataSeekPoint used to indicate a placeholder - * point (== 0xffffffffffffffff). - */ -extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; - - -/** FLAC SEEKTABLE structure. (c.f. format specification) - * - * \note From the format specification: - * - The seek points must be sorted by ascending sample number. - * - Each seek point's sample number must be the first sample of the - * target frame. - * - Each seek point's sample number must be unique within the table. - * - Existence of a SEEKTABLE block implies a correct setting of - * total_samples in the stream_info block. - * - Behavior is undefined when more than one SEEKTABLE block is - * present in a stream. - */ -typedef struct { - unsigned num_points; - FLAC__StreamMetadata_SeekPoint *points; -} FLAC__StreamMetadata_SeekTable; - - -/** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. format specification) - * - * For convenience, the APIs maintain a trailing NUL character at the end of - * \a entry which is not counted toward \a length, i.e. - * \code strlen(entry) == length \endcode - */ -typedef struct { - FLAC__uint32 length; - FLAC__byte *entry; -} FLAC__StreamMetadata_VorbisComment_Entry; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */ - - -/** FLAC VORBIS_COMMENT structure. (c.f. format specification) - */ -typedef struct { - FLAC__StreamMetadata_VorbisComment_Entry vendor_string; - FLAC__uint32 num_comments; - FLAC__StreamMetadata_VorbisComment_Entry *comments; -} FLAC__StreamMetadata_VorbisComment; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */ - - -/** FLAC CUESHEET track index structure. (See the - * format specification for - * the full description of each field.) - */ -typedef struct { - FLAC__uint64 offset; - /**< Offset in samples, relative to the track offset, of the index - * point. - */ - - FLAC__byte number; - /**< The index point number. */ -} FLAC__StreamMetadata_CueSheet_Index; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */ - - -/** FLAC CUESHEET track structure. (See the - * format specification for - * the full description of each field.) - */ -typedef struct { - FLAC__uint64 offset; - /**< Track offset in samples, relative to the beginning of the FLAC audio stream. */ - - FLAC__byte number; - /**< The track number. */ - - char isrc[13]; - /**< Track ISRC. This is a 12-digit alphanumeric code plus a trailing \c NUL byte */ - - unsigned type:1; - /**< The track type: 0 for audio, 1 for non-audio. */ - - unsigned pre_emphasis:1; - /**< The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. */ - - FLAC__byte num_indices; - /**< The number of track index points. */ - - FLAC__StreamMetadata_CueSheet_Index *indices; - /**< NULL if num_indices == 0, else pointer to array of index points. */ - -} FLAC__StreamMetadata_CueSheet_Track; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */ - - -/** FLAC CUESHEET structure. (See the - * format specification - * for the full description of each field.) - */ -typedef struct { - char media_catalog_number[129]; - /**< Media catalog number, in ASCII printable characters 0x20-0x7e. In - * general, the media catalog number may be 0 to 128 bytes long; any - * unused characters should be right-padded with NUL characters. - */ - - FLAC__uint64 lead_in; - /**< The number of lead-in samples. */ - - FLAC__bool is_cd; - /**< \c true if CUESHEET corresponds to a Compact Disc, else \c false. */ - - unsigned num_tracks; - /**< The number of tracks. */ - - FLAC__StreamMetadata_CueSheet_Track *tracks; - /**< NULL if num_tracks == 0, else pointer to array of tracks. */ - -} FLAC__StreamMetadata_CueSheet; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */ - - -/** An enumeration of the PICTURE types (see FLAC__StreamMetadataPicture and id3 v2.4 APIC tag). */ -typedef enum { - FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER = 0, /**< Other */ - FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD = 1, /**< 32x32 pixels 'file icon' (PNG only) */ - FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON = 2, /**< Other file icon */ - FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER = 3, /**< Cover (front) */ - FLAC__STREAM_METADATA_PICTURE_TYPE_BACK_COVER = 4, /**< Cover (back) */ - FLAC__STREAM_METADATA_PICTURE_TYPE_LEAFLET_PAGE = 5, /**< Leaflet page */ - FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA = 6, /**< Media (e.g. label side of CD) */ - FLAC__STREAM_METADATA_PICTURE_TYPE_LEAD_ARTIST = 7, /**< Lead artist/lead performer/soloist */ - FLAC__STREAM_METADATA_PICTURE_TYPE_ARTIST = 8, /**< Artist/performer */ - FLAC__STREAM_METADATA_PICTURE_TYPE_CONDUCTOR = 9, /**< Conductor */ - FLAC__STREAM_METADATA_PICTURE_TYPE_BAND = 10, /**< Band/Orchestra */ - FLAC__STREAM_METADATA_PICTURE_TYPE_COMPOSER = 11, /**< Composer */ - FLAC__STREAM_METADATA_PICTURE_TYPE_LYRICIST = 12, /**< Lyricist/text writer */ - FLAC__STREAM_METADATA_PICTURE_TYPE_RECORDING_LOCATION = 13, /**< Recording Location */ - FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_RECORDING = 14, /**< During recording */ - FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_PERFORMANCE = 15, /**< During performance */ - FLAC__STREAM_METADATA_PICTURE_TYPE_VIDEO_SCREEN_CAPTURE = 16, /**< Movie/video screen capture */ - FLAC__STREAM_METADATA_PICTURE_TYPE_FISH = 17, /**< A bright coloured fish */ - FLAC__STREAM_METADATA_PICTURE_TYPE_ILLUSTRATION = 18, /**< Illustration */ - FLAC__STREAM_METADATA_PICTURE_TYPE_BAND_LOGOTYPE = 19, /**< Band/artist logotype */ - FLAC__STREAM_METADATA_PICTURE_TYPE_PUBLISHER_LOGOTYPE = 20, /**< Publisher/Studio logotype */ - FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED -} FLAC__StreamMetadata_Picture_Type; - -/** Maps a FLAC__StreamMetadata_Picture_Type to a C string. - * - * Using a FLAC__StreamMetadata_Picture_Type as the index to this array - * will give the string equivalent. The contents should not be - * modified. - */ -extern FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[]; - -/** FLAC PICTURE structure. (See the - * format specification - * for the full description of each field.) - */ -typedef struct { - FLAC__StreamMetadata_Picture_Type type; - /**< The kind of picture stored. */ - - char *mime_type; - /**< Picture data's MIME type, in ASCII printable characters - * 0x20-0x7e, NUL terminated. For best compatibility with players, - * use picture data of MIME type \c image/jpeg or \c image/png. A - * MIME type of '-->' is also allowed, in which case the picture - * data should be a complete URL. In file storage, the MIME type is - * stored as a 32-bit length followed by the ASCII string with no NUL - * terminator, but is converted to a plain C string in this structure - * for convenience. - */ - - FLAC__byte *description; - /**< Picture's description in UTF-8, NUL terminated. In file storage, - * the description is stored as a 32-bit length followed by the UTF-8 - * string with no NUL terminator, but is converted to a plain C string - * in this structure for convenience. - */ - - FLAC__uint32 width; - /**< Picture's width in pixels. */ - - FLAC__uint32 height; - /**< Picture's height in pixels. */ - - FLAC__uint32 depth; - /**< Picture's color depth in bits-per-pixel. */ - - FLAC__uint32 colors; - /**< For indexed palettes (like GIF), picture's number of colors (the - * number of palette entries), or \c 0 for non-indexed (i.e. 2^depth). - */ - - FLAC__uint32 data_length; - /**< Length of binary picture data in bytes. */ - - FLAC__byte *data; - /**< Binary picture data. */ - -} FLAC__StreamMetadata_Picture; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN; /**< == 32 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN; /**< == 32 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN; /**< == 32 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN; /**< == 32 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN; /**< == 32 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN; /**< == 32 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN; /**< == 32 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN; /**< == 32 (bits) */ - - -/** Structure that is used when a metadata block of unknown type is loaded. - * The contents are opaque. The structure is used only internally to - * correctly handle unknown metadata. - */ -typedef struct { - FLAC__byte *data; -} FLAC__StreamMetadata_Unknown; - - -/** FLAC metadata block structure. (c.f. format specification) - */ -typedef struct { - FLAC__MetadataType type; - /**< The type of the metadata block; used determine which member of the - * \a data union to dereference. If type >= FLAC__METADATA_TYPE_UNDEFINED - * then \a data.unknown must be used. */ - - FLAC__bool is_last; - /**< \c true if this metadata block is the last, else \a false */ - - unsigned length; - /**< Length, in bytes, of the block data as it appears in the stream. */ - - union { - FLAC__StreamMetadata_StreamInfo stream_info; - FLAC__StreamMetadata_Padding padding; - FLAC__StreamMetadata_Application application; - FLAC__StreamMetadata_SeekTable seek_table; - FLAC__StreamMetadata_VorbisComment vorbis_comment; - FLAC__StreamMetadata_CueSheet cue_sheet; - FLAC__StreamMetadata_Picture picture; - FLAC__StreamMetadata_Unknown unknown; - } data; - /**< Polymorphic block data; use the \a type value to determine which - * to use. */ -} FLAC__StreamMetadata; - -extern FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */ -extern FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */ - -/** The total stream length of a metadata block header in bytes. */ -#define FLAC__STREAM_METADATA_HEADER_LENGTH (4u) - -/*****************************************************************************/ - - -/***************************************************************************** - * - * Utility functions - * - *****************************************************************************/ - -/** Tests that a sample rate is valid for FLAC. - * - * \param sample_rate The sample rate to test for compliance. - * \retval FLAC__bool - * \c true if the given sample rate conforms to the specification, else - * \c false. - */ -FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate); - -/** Tests that a blocksize at the given sample rate is valid for the FLAC - * subset. - * - * \param blocksize The blocksize to test for compliance. - * \param sample_rate The sample rate is needed, since the valid subset - * blocksize depends on the sample rate. - * \retval FLAC__bool - * \c true if the given blocksize conforms to the specification for the - * subset at the given sample rate, else \c false. - */ -FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(unsigned blocksize, unsigned sample_rate); - -/** Tests that a sample rate is valid for the FLAC subset. The subset rules - * for valid sample rates are slightly more complex since the rate has to - * be expressible completely in the frame header. - * - * \param sample_rate The sample rate to test for compliance. - * \retval FLAC__bool - * \c true if the given sample rate conforms to the specification for the - * subset, else \c false. - */ -FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate); - -/** Check a Vorbis comment entry name to see if it conforms to the Vorbis - * comment specification. - * - * Vorbis comment names must be composed only of characters from - * [0x20-0x3C,0x3E-0x7D]. - * - * \param name A NUL-terminated string to be checked. - * \assert - * \code name != NULL \endcode - * \retval FLAC__bool - * \c false if entry name is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name); - -/** Check a Vorbis comment entry value to see if it conforms to the Vorbis - * comment specification. - * - * Vorbis comment values must be valid UTF-8 sequences. - * - * \param value A string to be checked. - * \param length A the length of \a value in bytes. May be - * \c (unsigned)(-1) to indicate that \a value is a plain - * UTF-8 NUL-terminated string. - * \assert - * \code value != NULL \endcode - * \retval FLAC__bool - * \c false if entry name is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length); - -/** Check a Vorbis comment entry to see if it conforms to the Vorbis - * comment specification. - * - * Vorbis comment entries must be of the form 'name=value', and 'name' and - * 'value' must be legal according to - * FLAC__format_vorbiscomment_entry_name_is_legal() and - * FLAC__format_vorbiscomment_entry_value_is_legal() respectively. - * - * \param entry An entry to be checked. - * \param length The length of \a entry in bytes. - * \assert - * \code value != NULL \endcode - * \retval FLAC__bool - * \c false if entry name is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length); - -/** Check a seek table to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * seek table. - * - * \param seek_table A pointer to a seek table to be checked. - * \assert - * \code seek_table != NULL \endcode - * \retval FLAC__bool - * \c false if seek table is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table); - -/** Sort a seek table's seek points according to the format specification. - * This includes a "unique-ification" step to remove duplicates, i.e. - * seek points with identical \a sample_number values. Duplicate seek - * points are converted into placeholder points and sorted to the end of - * the table. - * - * \param seek_table A pointer to a seek table to be sorted. - * \assert - * \code seek_table != NULL \endcode - * \retval unsigned - * The number of duplicate seek points converted into placeholders. - */ -FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table); - -/** Check a cue sheet to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * cue sheet. - * - * \param cue_sheet A pointer to an existing cue sheet to be checked. - * \param check_cd_da_subset If \c true, check CUESHEET against more - * stringent requirements for a CD-DA (audio) disc. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code cue_sheet != NULL \endcode - * \retval FLAC__bool - * \c false if cue sheet is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation); - -/** Check picture data to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * PICTURE block. - * - * \param picture A pointer to existing picture data to be checked. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code picture != NULL \endcode - * \retval FLAC__bool - * \c false if picture data is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation); - -/* \} */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/Windows/include/FLAC/metadata.h b/platform/Windows/include/FLAC/metadata.h deleted file mode 100644 index fcc8ed95c..000000000 --- a/platform/Windows/include/FLAC/metadata.h +++ /dev/null @@ -1,2182 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__METADATA_H -#define FLAC__METADATA_H - -#include /* for off_t */ -#include "export.h" -#include "callback.h" -#include "format.h" - -/* -------------------------------------------------------------------- - (For an example of how all these routines are used, see the source - code for the unit tests in src/test_libFLAC/metadata_*.c, or - metaflac in src/metaflac/) - ------------------------------------------------------------------*/ - -/** \file include/FLAC/metadata.h - * - * \brief - * This module provides functions for creating and manipulating FLAC - * metadata blocks in memory, and three progressively more powerful - * interfaces for traversing and editing metadata in FLAC files. - * - * See the detailed documentation for each interface in the - * \link flac_metadata metadata \endlink module. - */ - -/** \defgroup flac_metadata FLAC/metadata.h: metadata interfaces - * \ingroup flac - * - * \brief - * This module provides functions for creating and manipulating FLAC - * metadata blocks in memory, and three progressively more powerful - * interfaces for traversing and editing metadata in native FLAC files. - * Note that currently only the Chain interface (level 2) supports Ogg - * FLAC files, and it is read-only i.e. no writing back changed - * metadata to file. - * - * There are three metadata interfaces of increasing complexity: - * - * Level 0: - * Read-only access to the STREAMINFO, VORBIS_COMMENT, CUESHEET, and - * PICTURE blocks. - * - * Level 1: - * Read-write access to all metadata blocks. This level is write- - * efficient in most cases (more on this below), and uses less memory - * than level 2. - * - * Level 2: - * Read-write access to all metadata blocks. This level is write- - * efficient in all cases, but uses more memory since all metadata for - * the whole file is read into memory and manipulated before writing - * out again. - * - * What do we mean by efficient? Since FLAC metadata appears at the - * beginning of the file, when writing metadata back to a FLAC file - * it is possible to grow or shrink the metadata such that the entire - * file must be rewritten. However, if the size remains the same during - * changes or PADDING blocks are utilized, only the metadata needs to be - * overwritten, which is much faster. - * - * Efficient means the whole file is rewritten at most one time, and only - * when necessary. Level 1 is not efficient only in the case that you - * cause more than one metadata block to grow or shrink beyond what can - * be accomodated by padding. In this case you should probably use level - * 2, which allows you to edit all the metadata for a file in memory and - * write it out all at once. - * - * All levels know how to skip over and not disturb an ID3v2 tag at the - * front of the file. - * - * All levels access files via their filenames. In addition, level 2 - * has additional alternative read and write functions that take an I/O - * handle and callbacks, for situations where access by filename is not - * possible. - * - * In addition to the three interfaces, this module defines functions for - * creating and manipulating various metadata objects in memory. As we see - * from the Format module, FLAC metadata blocks in memory are very primitive - * structures for storing information in an efficient way. Reading - * information from the structures is easy but creating or modifying them - * directly is more complex. The metadata object routines here facilitate - * this by taking care of the consistency and memory management drudgery. - * - * Unless you will be using the level 1 or 2 interfaces to modify existing - * metadata however, you will not probably not need these. - * - * From a dependency standpoint, none of the encoders or decoders require - * the metadata module. This is so that embedded users can strip out the - * metadata module from libFLAC to reduce the size and complexity. - */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/** \defgroup flac_metadata_level0 FLAC/metadata.h: metadata level 0 interface - * \ingroup flac_metadata - * - * \brief - * The level 0 interface consists of individual routines to read the - * STREAMINFO, VORBIS_COMMENT, CUESHEET, and PICTURE blocks, requiring - * only a filename. - * - * They try to skip any ID3v2 tag at the head of the file. - * - * \{ - */ - -/** Read the STREAMINFO metadata block of the given FLAC file. This function - * will try to skip any ID3v2 tag at the head of the file. - * - * \param filename The path to the FLAC file to read. - * \param streaminfo A pointer to space for the STREAMINFO block. Since - * FLAC__StreamMetadata is a simple structure with no - * memory allocation involved, you pass the address of - * an existing structure. It need not be initialized. - * \assert - * \code filename != NULL \endcode - * \code streaminfo != NULL \endcode - * \retval FLAC__bool - * \c true if a valid STREAMINFO block was read from \a filename. Returns - * \c false if there was a memory allocation error, a file decoder error, - * or the file contained no STREAMINFO block. (A memory allocation error - * is possible because this function must set up a file decoder.) - */ -FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo); - -/** Read the VORBIS_COMMENT metadata block of the given FLAC file. This - * function will try to skip any ID3v2 tag at the head of the file. - * - * \param filename The path to the FLAC file to read. - * \param tags The address where the returned pointer will be - * stored. The \a tags object must be deleted by - * the caller using FLAC__metadata_object_delete(). - * \assert - * \code filename != NULL \endcode - * \code tags != NULL \endcode - * \retval FLAC__bool - * \c true if a valid VORBIS_COMMENT block was read from \a filename, - * and \a *tags will be set to the address of the metadata structure. - * Returns \c false if there was a memory allocation error, a file - * decoder error, or the file contained no VORBIS_COMMENT block, and - * \a *tags will be set to \c NULL. - */ -FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags); - -/** Read the CUESHEET metadata block of the given FLAC file. This - * function will try to skip any ID3v2 tag at the head of the file. - * - * \param filename The path to the FLAC file to read. - * \param cuesheet The address where the returned pointer will be - * stored. The \a cuesheet object must be deleted by - * the caller using FLAC__metadata_object_delete(). - * \assert - * \code filename != NULL \endcode - * \code cuesheet != NULL \endcode - * \retval FLAC__bool - * \c true if a valid CUESHEET block was read from \a filename, - * and \a *cuesheet will be set to the address of the metadata - * structure. Returns \c false if there was a memory allocation - * error, a file decoder error, or the file contained no CUESHEET - * block, and \a *cuesheet will be set to \c NULL. - */ -FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet); - -/** Read a PICTURE metadata block of the given FLAC file. This - * function will try to skip any ID3v2 tag at the head of the file. - * Since there can be more than one PICTURE block in a file, this - * function takes a number of parameters that act as constraints to - * the search. The PICTURE block with the largest area matching all - * the constraints will be returned, or \a *picture will be set to - * \c NULL if there was no such block. - * - * \param filename The path to the FLAC file to read. - * \param picture The address where the returned pointer will be - * stored. The \a picture object must be deleted by - * the caller using FLAC__metadata_object_delete(). - * \param type The desired picture type. Use \c -1 to mean - * "any type". - * \param mime_type The desired MIME type, e.g. "image/jpeg". The - * string will be matched exactly. Use \c NULL to - * mean "any MIME type". - * \param description The desired description. The string will be - * matched exactly. Use \c NULL to mean "any - * description". - * \param max_width The maximum width in pixels desired. Use - * \c (unsigned)(-1) to mean "any width". - * \param max_height The maximum height in pixels desired. Use - * \c (unsigned)(-1) to mean "any height". - * \param max_depth The maximum color depth in bits-per-pixel desired. - * Use \c (unsigned)(-1) to mean "any depth". - * \param max_colors The maximum number of colors desired. Use - * \c (unsigned)(-1) to mean "any number of colors". - * \assert - * \code filename != NULL \endcode - * \code picture != NULL \endcode - * \retval FLAC__bool - * \c true if a valid PICTURE block was read from \a filename, - * and \a *picture will be set to the address of the metadata - * structure. Returns \c false if there was a memory allocation - * error, a file decoder error, or the file contained no PICTURE - * block, and \a *picture will be set to \c NULL. - */ -FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors); - -/* \} */ - - -/** \defgroup flac_metadata_level1 FLAC/metadata.h: metadata level 1 interface - * \ingroup flac_metadata - * - * \brief - * The level 1 interface provides read-write access to FLAC file metadata and - * operates directly on the FLAC file. - * - * The general usage of this interface is: - * - * - Create an iterator using FLAC__metadata_simple_iterator_new() - * - Attach it to a file using FLAC__metadata_simple_iterator_init() and check - * the exit code. Call FLAC__metadata_simple_iterator_is_writable() to - * see if the file is writable, or only read access is allowed. - * - Use FLAC__metadata_simple_iterator_next() and - * FLAC__metadata_simple_iterator_prev() to traverse the blocks. - * This is does not read the actual blocks themselves. - * FLAC__metadata_simple_iterator_next() is relatively fast. - * FLAC__metadata_simple_iterator_prev() is slower since it needs to search - * forward from the front of the file. - * - Use FLAC__metadata_simple_iterator_get_block_type() or - * FLAC__metadata_simple_iterator_get_block() to access the actual data at - * the current iterator position. The returned object is yours to modify - * and free. - * - Use FLAC__metadata_simple_iterator_set_block() to write a modified block - * back. You must have write permission to the original file. Make sure to - * read the whole comment to FLAC__metadata_simple_iterator_set_block() - * below. - * - Use FLAC__metadata_simple_iterator_insert_block_after() to add new blocks. - * Use the object creation functions from - * \link flac_metadata_object here \endlink to generate new objects. - * - Use FLAC__metadata_simple_iterator_delete_block() to remove the block - * currently referred to by the iterator, or replace it with padding. - * - Destroy the iterator with FLAC__metadata_simple_iterator_delete() when - * finished. - * - * \note - * The FLAC file remains open the whole time between - * FLAC__metadata_simple_iterator_init() and - * FLAC__metadata_simple_iterator_delete(), so make sure you are not altering - * the file during this time. - * - * \note - * Do not modify the \a is_last, \a length, or \a type fields of returned - * FLAC__StreamMetadata objects. These are managed automatically. - * - * \note - * If any of the modification functions - * (FLAC__metadata_simple_iterator_set_block(), - * FLAC__metadata_simple_iterator_delete_block(), - * FLAC__metadata_simple_iterator_insert_block_after(), etc.) return \c false, - * you should delete the iterator as it may no longer be valid. - * - * \{ - */ - -struct FLAC__Metadata_SimpleIterator; -/** The opaque structure definition for the level 1 iterator type. - * See the - * \link flac_metadata_level1 metadata level 1 module \endlink - * for a detailed description. - */ -typedef struct FLAC__Metadata_SimpleIterator FLAC__Metadata_SimpleIterator; - -/** Status type for FLAC__Metadata_SimpleIterator. - * - * The iterator's current status can be obtained by calling FLAC__metadata_simple_iterator_status(). - */ -typedef enum { - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK = 0, - /**< The iterator is in the normal OK state */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT, - /**< The data passed into a function violated the function's usage criteria */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE, - /**< The iterator could not open the target file */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE, - /**< The iterator could not find the FLAC signature at the start of the file */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE, - /**< The iterator tried to write to a file that was not writable */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA, - /**< The iterator encountered input that does not conform to the FLAC metadata specification */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR, - /**< The iterator encountered an error while reading the FLAC file */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR, - /**< The iterator encountered an error while seeking in the FLAC file */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR, - /**< The iterator encountered an error while writing the FLAC file */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR, - /**< The iterator encountered an error renaming the FLAC file */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR, - /**< The iterator encountered an error removing the temporary file */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR, - /**< Memory allocation failed */ - - FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR - /**< The caller violated an assertion or an unexpected error occurred */ - -} FLAC__Metadata_SimpleIteratorStatus; - -/** Maps a FLAC__Metadata_SimpleIteratorStatus to a C string. - * - * Using a FLAC__Metadata_SimpleIteratorStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[]; - - -/** Create a new iterator instance. - * - * \retval FLAC__Metadata_SimpleIterator* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void); - -/** Free an iterator instance. Deletes the object pointed to by \a iterator. - * - * \param iterator A pointer to an existing iterator. - * \assert - * \code iterator != NULL \endcode - */ -FLAC_API void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator); - -/** Get the current status of the iterator. Call this after a function - * returns \c false to get the reason for the error. Also resets the status - * to FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK. - * - * \param iterator A pointer to an existing iterator. - * \assert - * \code iterator != NULL \endcode - * \retval FLAC__Metadata_SimpleIteratorStatus - * The current status of the iterator. - */ -FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator); - -/** Initialize the iterator to point to the first metadata block in the - * given FLAC file. - * - * \param iterator A pointer to an existing iterator. - * \param filename The path to the FLAC file. - * \param read_only If \c true, the FLAC file will be opened - * in read-only mode; if \c false, the FLAC - * file will be opened for edit even if no - * edits are performed. - * \param preserve_file_stats If \c true, the owner and modification - * time will be preserved even if the FLAC - * file is written to. - * \assert - * \code iterator != NULL \endcode - * \code filename != NULL \endcode - * \retval FLAC__bool - * \c false if a memory allocation error occurs, the file can't be - * opened, or another error occurs, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool read_only, FLAC__bool preserve_file_stats); - -/** Returns \c true if the FLAC file is writable. If \c false, calls to - * FLAC__metadata_simple_iterator_set_block() and - * FLAC__metadata_simple_iterator_insert_block_after() will fail. - * - * \param iterator A pointer to an existing iterator. - * \assert - * \code iterator != NULL \endcode - * \retval FLAC__bool - * See above. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator *iterator); - -/** Moves the iterator forward one metadata block, returning \c false if - * already at the end. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c false if already at the last metadata block of the chain, else - * \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator *iterator); - -/** Moves the iterator backward one metadata block, returning \c false if - * already at the beginning. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c false if already at the first metadata block of the chain, else - * \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator); - -/** Returns a flag telling if the current metadata block is the last. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c true if the current metadata block is the last in the file, - * else \c false. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_last(const FLAC__Metadata_SimpleIterator *iterator); - -/** Get the offset of the metadata block at the current position. This - * avoids reading the actual block data which can save time for large - * blocks. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval off_t - * The offset of the metadata block at the current iterator position. - * This is the byte offset relative to the beginning of the file of - * the current metadata block's header. - */ -FLAC_API off_t FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metadata_SimpleIterator *iterator); - -/** Get the type of the metadata block at the current position. This - * avoids reading the actual block data which can save time for large - * blocks. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__MetadataType - * The type of the metadata block at the current iterator position. - */ -FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator); - -/** Get the length of the metadata block at the current position. This - * avoids reading the actual block data which can save time for large - * blocks. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval unsigned - * The length of the metadata block at the current iterator position. - * The is same length as that in the - * metadata block header, - * i.e. the length of the metadata body that follows the header. - */ -FLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator); - -/** Get the application ID of the \c APPLICATION block at the current - * position. This avoids reading the actual block data which can save - * time for large blocks. - * - * \param iterator A pointer to an existing initialized iterator. - * \param id A pointer to a buffer of at least \c 4 bytes where - * the ID will be stored. - * \assert - * \code iterator != NULL \endcode - * \code id != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c true if the ID was successfully read, else \c false, in which - * case you should check FLAC__metadata_simple_iterator_status() to - * find out why. If the status is - * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT, then the - * current metadata block is not an \c APPLICATION block. Otherwise - * if the status is - * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR or - * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR, an I/O error - * occurred and the iterator can no longer be used. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_get_application_id(FLAC__Metadata_SimpleIterator *iterator, FLAC__byte *id); - -/** Get the metadata block at the current position. You can modify the - * block but must use FLAC__metadata_simple_iterator_set_block() to - * write it back to the FLAC file. - * - * You must call FLAC__metadata_object_delete() on the returned object - * when you are finished with it. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__StreamMetadata* - * The current metadata block, or \c NULL if there was a memory - * allocation error. - */ -FLAC_API FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator); - -/** Write a block back to the FLAC file. This function tries to be - * as efficient as possible; how the block is actually written is - * shown by the following: - * - * Existing block is a STREAMINFO block and the new block is a - * STREAMINFO block: the new block is written in place. Make sure - * you know what you're doing when changing the values of a - * STREAMINFO block. - * - * Existing block is a STREAMINFO block and the new block is a - * not a STREAMINFO block: this is an error since the first block - * must be a STREAMINFO block. Returns \c false without altering the - * file. - * - * Existing block is not a STREAMINFO block and the new block is a - * STREAMINFO block: this is an error since there may be only one - * STREAMINFO block. Returns \c false without altering the file. - * - * Existing block and new block are the same length: the existing - * block will be replaced by the new block, written in place. - * - * Existing block is longer than new block: if use_padding is \c true, - * the existing block will be overwritten in place with the new - * block followed by a PADDING block, if possible, to make the total - * size the same as the existing block. Remember that a padding - * block requires at least four bytes so if the difference in size - * between the new block and existing block is less than that, the - * entire file will have to be rewritten, using the new block's - * exact size. If use_padding is \c false, the entire file will be - * rewritten, replacing the existing block by the new block. - * - * Existing block is shorter than new block: if use_padding is \c true, - * the function will try and expand the new block into the following - * PADDING block, if it exists and doing so won't shrink the PADDING - * block to less than 4 bytes. If there is no following PADDING - * block, or it will shrink to less than 4 bytes, or use_padding is - * \c false, the entire file is rewritten, replacing the existing block - * with the new block. Note that in this case any following PADDING - * block is preserved as is. - * - * After writing the block, the iterator will remain in the same - * place, i.e. pointing to the new block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block The block to set. - * \param use_padding See above. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \code block != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding); - -/** This is similar to FLAC__metadata_simple_iterator_set_block() - * except that instead of writing over an existing block, it appends - * a block after the existing block. \a use_padding is again used to - * tell the function to try an expand into following padding in an - * attempt to avoid rewriting the entire file. - * - * This function will fail and return \c false if given a STREAMINFO - * block. - * - * After writing the block, the iterator will be pointing to the - * new block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block The block to set. - * \param use_padding See above. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \code block != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding); - -/** Deletes the block at the current position. This will cause the - * entire FLAC file to be rewritten, unless \a use_padding is \c true, - * in which case the block will be replaced by an equal-sized PADDING - * block. The iterator will be left pointing to the block before the - * one just deleted. - * - * You may not delete the STREAMINFO block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param use_padding See above. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c true if successful, else \c false. - */ -FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding); - -/* \} */ - - -/** \defgroup flac_metadata_level2 FLAC/metadata.h: metadata level 2 interface - * \ingroup flac_metadata - * - * \brief - * The level 2 interface provides read-write access to FLAC file metadata; - * all metadata is read into memory, operated on in memory, and then written - * to file, which is more efficient than level 1 when editing multiple blocks. - * - * Currently Ogg FLAC is supported for read only, via - * FLAC__metadata_chain_read_ogg() but a subsequent - * FLAC__metadata_chain_write() will fail. - * - * The general usage of this interface is: - * - * - Create a new chain using FLAC__metadata_chain_new(). A chain is a - * linked list of FLAC metadata blocks. - * - Read all metadata into the the chain from a FLAC file using - * FLAC__metadata_chain_read() or FLAC__metadata_chain_read_ogg() and - * check the status. - * - Optionally, consolidate the padding using - * FLAC__metadata_chain_merge_padding() or - * FLAC__metadata_chain_sort_padding(). - * - Create a new iterator using FLAC__metadata_iterator_new() - * - Initialize the iterator to point to the first element in the chain - * using FLAC__metadata_iterator_init() - * - Traverse the chain using FLAC__metadata_iterator_next and - * FLAC__metadata_iterator_prev(). - * - Get a block for reading or modification using - * FLAC__metadata_iterator_get_block(). The pointer to the object - * inside the chain is returned, so the block is yours to modify. - * Changes will be reflected in the FLAC file when you write the - * chain. You can also add and delete blocks (see functions below). - * - When done, write out the chain using FLAC__metadata_chain_write(). - * Make sure to read the whole comment to the function below. - * - Delete the chain using FLAC__metadata_chain_delete(). - * - * \note - * Even though the FLAC file is not open while the chain is being - * manipulated, you must not alter the file externally during - * this time. The chain assumes the FLAC file will not change - * between the time of FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg() - * and FLAC__metadata_chain_write(). - * - * \note - * Do not modify the is_last, length, or type fields of returned - * FLAC__StreamMetadata objects. These are managed automatically. - * - * \note - * The metadata objects returned by FLAC__metadata_iterator_get_block() - * are owned by the chain; do not FLAC__metadata_object_delete() them. - * In the same way, blocks passed to FLAC__metadata_iterator_set_block() - * become owned by the chain and they will be deleted when the chain is - * deleted. - * - * \{ - */ - -struct FLAC__Metadata_Chain; -/** The opaque structure definition for the level 2 chain type. - */ -typedef struct FLAC__Metadata_Chain FLAC__Metadata_Chain; - -struct FLAC__Metadata_Iterator; -/** The opaque structure definition for the level 2 iterator type. - */ -typedef struct FLAC__Metadata_Iterator FLAC__Metadata_Iterator; - -typedef enum { - FLAC__METADATA_CHAIN_STATUS_OK = 0, - /**< The chain is in the normal OK state */ - - FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT, - /**< The data passed into a function violated the function's usage criteria */ - - FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE, - /**< The chain could not open the target file */ - - FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE, - /**< The chain could not find the FLAC signature at the start of the file */ - - FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE, - /**< The chain tried to write to a file that was not writable */ - - FLAC__METADATA_CHAIN_STATUS_BAD_METADATA, - /**< The chain encountered input that does not conform to the FLAC metadata specification */ - - FLAC__METADATA_CHAIN_STATUS_READ_ERROR, - /**< The chain encountered an error while reading the FLAC file */ - - FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR, - /**< The chain encountered an error while seeking in the FLAC file */ - - FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR, - /**< The chain encountered an error while writing the FLAC file */ - - FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR, - /**< The chain encountered an error renaming the FLAC file */ - - FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR, - /**< The chain encountered an error removing the temporary file */ - - FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR, - /**< Memory allocation failed */ - - FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR, - /**< The caller violated an assertion or an unexpected error occurred */ - - FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS, - /**< One or more of the required callbacks was NULL */ - - FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH, - /**< FLAC__metadata_chain_write() was called on a chain read by - * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), - * or - * FLAC__metadata_chain_write_with_callbacks()/FLAC__metadata_chain_write_with_callbacks_and_tempfile() - * was called on a chain read by - * FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). - * Matching read/write methods must always be used. */ - - FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL - /**< FLAC__metadata_chain_write_with_callbacks() was called when the - * chain write requires a tempfile; use - * FLAC__metadata_chain_write_with_callbacks_and_tempfile() instead. - * Or, FLAC__metadata_chain_write_with_callbacks_and_tempfile() was - * called when the chain write does not require a tempfile; use - * FLAC__metadata_chain_write_with_callbacks() instead. - * Always check FLAC__metadata_chain_check_if_tempfile_needed() - * before writing via callbacks. */ - -} FLAC__Metadata_ChainStatus; - -/** Maps a FLAC__Metadata_ChainStatus to a C string. - * - * Using a FLAC__Metadata_ChainStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__Metadata_ChainStatusString[]; - -/*********** FLAC__Metadata_Chain ***********/ - -/** Create a new chain instance. - * - * \retval FLAC__Metadata_Chain* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void); - -/** Free a chain instance. Deletes the object pointed to by \a chain. - * - * \param chain A pointer to an existing chain. - * \assert - * \code chain != NULL \endcode - */ -FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain); - -/** Get the current status of the chain. Call this after a function - * returns \c false to get the reason for the error. Also resets the - * status to FLAC__METADATA_CHAIN_STATUS_OK. - * - * \param chain A pointer to an existing chain. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__Metadata_ChainStatus - * The current status of the chain. - */ -FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain); - -/** Read all metadata from a FLAC file into the chain. - * - * \param chain A pointer to an existing chain. - * \param filename The path to the FLAC file to read. - * \assert - * \code chain != NULL \endcode - * \code filename != NULL \endcode - * \retval FLAC__bool - * \c true if a valid list of metadata blocks was read from - * \a filename, else \c false. On failure, check the status with - * FLAC__metadata_chain_status(). - */ -FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename); - -/** Read all metadata from an Ogg FLAC file into the chain. - * - * \note Ogg FLAC metadata data writing is not supported yet and - * FLAC__metadata_chain_write() will fail. - * - * \param chain A pointer to an existing chain. - * \param filename The path to the Ogg FLAC file to read. - * \assert - * \code chain != NULL \endcode - * \code filename != NULL \endcode - * \retval FLAC__bool - * \c true if a valid list of metadata blocks was read from - * \a filename, else \c false. On failure, check the status with - * FLAC__metadata_chain_status(). - */ -FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename); - -/** Read all metadata from a FLAC stream into the chain via I/O callbacks. - * - * The \a handle need only be open for reading, but must be seekable. - * The equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" - * for Windows). - * - * \param chain A pointer to an existing chain. - * \param handle The I/O handle of the FLAC stream to read. The - * handle will NOT be closed after the metadata is read; - * that is the duty of the caller. - * \param callbacks - * A set of callbacks to use for I/O. The mandatory - * callbacks are \a read, \a seek, and \a tell. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if a valid list of metadata blocks was read from - * \a handle, else \c false. On failure, check the status with - * FLAC__metadata_chain_status(). - */ -FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); - -/** Read all metadata from an Ogg FLAC stream into the chain via I/O callbacks. - * - * The \a handle need only be open for reading, but must be seekable. - * The equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" - * for Windows). - * - * \note Ogg FLAC metadata data writing is not supported yet and - * FLAC__metadata_chain_write() will fail. - * - * \param chain A pointer to an existing chain. - * \param handle The I/O handle of the Ogg FLAC stream to read. The - * handle will NOT be closed after the metadata is read; - * that is the duty of the caller. - * \param callbacks - * A set of callbacks to use for I/O. The mandatory - * callbacks are \a read, \a seek, and \a tell. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if a valid list of metadata blocks was read from - * \a handle, else \c false. On failure, check the status with - * FLAC__metadata_chain_status(). - */ -FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); - -/** Checks if writing the given chain would require the use of a - * temporary file, or if it could be written in place. - * - * Under certain conditions, padding can be utilized so that writing - * edited metadata back to the FLAC file does not require rewriting the - * entire file. If rewriting is required, then a temporary workfile is - * required. When writing metadata using callbacks, you must check - * this function to know whether to call - * FLAC__metadata_chain_write_with_callbacks() or - * FLAC__metadata_chain_write_with_callbacks_and_tempfile(). When - * writing with FLAC__metadata_chain_write(), the temporary file is - * handled internally. - * - * \param chain A pointer to an existing chain. - * \param use_padding - * Whether or not padding will be allowed to be used - * during the write. The value of \a use_padding given - * here must match the value later passed to - * FLAC__metadata_chain_write_with_callbacks() or - * FLAC__metadata_chain_write_with_callbacks_with_tempfile(). - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if writing the current chain would require a tempfile, or - * \c false if metadata can be written in place. - */ -FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding); - -/** Write all metadata out to the FLAC file. This function tries to be as - * efficient as possible; how the metadata is actually written is shown by - * the following: - * - * If the current chain is the same size as the existing metadata, the new - * data is written in place. - * - * If the current chain is longer than the existing metadata, and - * \a use_padding is \c true, and the last block is a PADDING block of - * sufficient length, the function will truncate the final padding block - * so that the overall size of the metadata is the same as the existing - * metadata, and then just rewrite the metadata. Otherwise, if not all of - * the above conditions are met, the entire FLAC file must be rewritten. - * If you want to use padding this way it is a good idea to call - * FLAC__metadata_chain_sort_padding() first so that you have the maximum - * amount of padding to work with, unless you need to preserve ordering - * of the PADDING blocks for some reason. - * - * If the current chain is shorter than the existing metadata, and - * \a use_padding is \c true, and the final block is a PADDING block, the padding - * is extended to make the overall size the same as the existing data. If - * \a use_padding is \c true and the last block is not a PADDING block, a new - * PADDING block is added to the end of the new data to make it the same - * size as the existing data (if possible, see the note to - * FLAC__metadata_simple_iterator_set_block() about the four byte limit) - * and the new data is written in place. If none of the above apply or - * \a use_padding is \c false, the entire FLAC file is rewritten. - * - * If \a preserve_file_stats is \c true, the owner and modification time will - * be preserved even if the FLAC file is written. - * - * For this write function to be used, the chain must have been read with - * FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(), not - * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(). - * - * \param chain A pointer to an existing chain. - * \param use_padding See above. - * \param preserve_file_stats See above. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if the write succeeded, else \c false. On failure, - * check the status with FLAC__metadata_chain_status(). - */ -FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats); - -/** Write all metadata out to a FLAC stream via callbacks. - * - * (See FLAC__metadata_chain_write() for the details on how padding is - * used to write metadata in place if possible.) - * - * The \a handle must be open for updating and be seekable. The - * equivalent minimum stdio fopen() file mode is \c "r+" (or \c "r+b" - * for Windows). - * - * For this write function to be used, the chain must have been read with - * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), - * not FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). - * Also, FLAC__metadata_chain_check_if_tempfile_needed() must have returned - * \c false. - * - * \param chain A pointer to an existing chain. - * \param use_padding See FLAC__metadata_chain_write() - * \param handle The I/O handle of the FLAC stream to write. The - * handle will NOT be closed after the metadata is - * written; that is the duty of the caller. - * \param callbacks A set of callbacks to use for I/O. The mandatory - * callbacks are \a write and \a seek. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if the write succeeded, else \c false. On failure, - * check the status with FLAC__metadata_chain_status(). - */ -FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); - -/** Write all metadata out to a FLAC stream via callbacks. - * - * (See FLAC__metadata_chain_write() for the details on how padding is - * used to write metadata in place if possible.) - * - * This version of the write-with-callbacks function must be used when - * FLAC__metadata_chain_check_if_tempfile_needed() returns true. In - * this function, you must supply an I/O handle corresponding to the - * FLAC file to edit, and a temporary handle to which the new FLAC - * file will be written. It is the caller's job to move this temporary - * FLAC file on top of the original FLAC file to complete the metadata - * edit. - * - * The \a handle must be open for reading and be seekable. The - * equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" - * for Windows). - * - * The \a temp_handle must be open for writing. The - * equivalent minimum stdio fopen() file mode is \c "w" (or \c "wb" - * for Windows). It should be an empty stream, or at least positioned - * at the start-of-file (in which case it is the caller's duty to - * truncate it on return). - * - * For this write function to be used, the chain must have been read with - * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), - * not FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). - * Also, FLAC__metadata_chain_check_if_tempfile_needed() must have returned - * \c true. - * - * \param chain A pointer to an existing chain. - * \param use_padding See FLAC__metadata_chain_write() - * \param handle The I/O handle of the original FLAC stream to read. - * The handle will NOT be closed after the metadata is - * written; that is the duty of the caller. - * \param callbacks A set of callbacks to use for I/O on \a handle. - * The mandatory callbacks are \a read, \a seek, and - * \a eof. - * \param temp_handle The I/O handle of the FLAC stream to write. The - * handle will NOT be closed after the metadata is - * written; that is the duty of the caller. - * \param temp_callbacks - * A set of callbacks to use for I/O on temp_handle. - * The only mandatory callback is \a write. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if the write succeeded, else \c false. On failure, - * check the status with FLAC__metadata_chain_status(). - */ -FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks); - -/** Merge adjacent PADDING blocks into a single block. - * - * \note This function does not write to the FLAC file, it only - * modifies the chain. - * - * \warning Any iterator on the current chain will become invalid after this - * call. You should delete the iterator and get a new one. - * - * \param chain A pointer to an existing chain. - * \assert - * \code chain != NULL \endcode - */ -FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain); - -/** This function will move all PADDING blocks to the end on the metadata, - * then merge them into a single block. - * - * \note This function does not write to the FLAC file, it only - * modifies the chain. - * - * \warning Any iterator on the current chain will become invalid after this - * call. You should delete the iterator and get a new one. - * - * \param chain A pointer to an existing chain. - * \assert - * \code chain != NULL \endcode - */ -FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain); - - -/*********** FLAC__Metadata_Iterator ***********/ - -/** Create a new iterator instance. - * - * \retval FLAC__Metadata_Iterator* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void); - -/** Free an iterator instance. Deletes the object pointed to by \a iterator. - * - * \param iterator A pointer to an existing iterator. - * \assert - * \code iterator != NULL \endcode - */ -FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator); - -/** Initialize the iterator to point to the first metadata block in the - * given chain. - * - * \param iterator A pointer to an existing iterator. - * \param chain A pointer to an existing and initialized (read) chain. - * \assert - * \code iterator != NULL \endcode - * \code chain != NULL \endcode - */ -FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain); - -/** Moves the iterator forward one metadata block, returning \c false if - * already at the end. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if already at the last metadata block of the chain, else - * \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator); - -/** Moves the iterator backward one metadata block, returning \c false if - * already at the beginning. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if already at the first metadata block of the chain, else - * \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator); - -/** Get the type of the metadata block at the current position. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__MetadataType - * The type of the metadata block at the current iterator position. - */ -FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator); - -/** Get the metadata block at the current position. You can modify - * the block in place but must write the chain before the changes - * are reflected to the FLAC file. You do not need to call - * FLAC__metadata_iterator_set_block() to reflect the changes; - * the pointer returned by FLAC__metadata_iterator_get_block() - * points directly into the chain. - * - * \warning - * Do not call FLAC__metadata_object_delete() on the returned object; - * to delete a block use FLAC__metadata_iterator_delete_block(). - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__StreamMetadata* - * The current metadata block. - */ -FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator); - -/** Set the metadata block at the current position, replacing the existing - * block. The new block passed in becomes owned by the chain and it will be - * deleted when the chain is deleted. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block A pointer to a metadata block. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \code block != NULL \endcode - * \retval FLAC__bool - * \c false if the conditions in the above description are not met, or - * a memory allocation error occurs, otherwise \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); - -/** Removes the current block from the chain. If \a replace_with_padding is - * \c true, the block will instead be replaced with a padding block of equal - * size. You can not delete the STREAMINFO block. The iterator will be - * left pointing to the block before the one just "deleted", even if - * \a replace_with_padding is \c true. - * - * \param iterator A pointer to an existing initialized iterator. - * \param replace_with_padding See above. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if the conditions in the above description are not met, - * otherwise \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding); - -/** Insert a new block before the current block. You cannot insert a block - * before the first STREAMINFO block. You cannot insert a STREAMINFO block - * as there can be only one, the one that already exists at the head when you - * read in a chain. The chain takes ownership of the new block and it will be - * deleted when the chain is deleted. The iterator will be left pointing to - * the new block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block A pointer to a metadata block to insert. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if the conditions in the above description are not met, or - * a memory allocation error occurs, otherwise \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); - -/** Insert a new block after the current block. You cannot insert a STREAMINFO - * block as there can be only one, the one that already exists at the head when - * you read in a chain. The chain takes ownership of the new block and it will - * be deleted when the chain is deleted. The iterator will be left pointing to - * the new block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block A pointer to a metadata block to insert. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if the conditions in the above description are not met, or - * a memory allocation error occurs, otherwise \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); - -/* \} */ - - -/** \defgroup flac_metadata_object FLAC/metadata.h: metadata object methods - * \ingroup flac_metadata - * - * \brief - * This module contains methods for manipulating FLAC metadata objects. - * - * Since many are variable length we have to be careful about the memory - * management. We decree that all pointers to data in the object are - * owned by the object and memory-managed by the object. - * - * Use the FLAC__metadata_object_new() and FLAC__metadata_object_delete() - * functions to create all instances. When using the - * FLAC__metadata_object_set_*() functions to set pointers to data, set - * \a copy to \c true to have the function make it's own copy of the data, or - * to \c false to give the object ownership of your data. In the latter case - * your pointer must be freeable by free() and will be free()d when the object - * is FLAC__metadata_object_delete()d. It is legal to pass a null pointer as - * the data pointer to a FLAC__metadata_object_set_*() function as long as - * the length argument is 0 and the \a copy argument is \c false. - * - * The FLAC__metadata_object_new() and FLAC__metadata_object_clone() function - * will return \c NULL in the case of a memory allocation error, otherwise a new - * object. The FLAC__metadata_object_set_*() functions return \c false in the - * case of a memory allocation error. - * - * We don't have the convenience of C++ here, so note that the library relies - * on you to keep the types straight. In other words, if you pass, for - * example, a FLAC__StreamMetadata* that represents a STREAMINFO block to - * FLAC__metadata_object_application_set_data(), you will get an assertion - * failure. - * - * For convenience the FLAC__metadata_object_vorbiscomment_*() functions - * maintain a trailing NUL on each Vorbis comment entry. This is not counted - * toward the length or stored in the stream, but it can make working with plain - * comments (those that don't contain embedded-NULs in the value) easier. - * Entries passed into these functions have trailing NULs added if missing, and - * returned entries are guaranteed to have a trailing NUL. - * - * The FLAC__metadata_object_vorbiscomment_*() functions that take a Vorbis - * comment entry/name/value will first validate that it complies with the Vorbis - * comment specification and return false if it does not. - * - * There is no need to recalculate the length field on metadata blocks you - * have modified. They will be calculated automatically before they are - * written back to a file. - * - * \{ - */ - - -/** Create a new metadata object instance of the given type. - * - * The object will be "empty"; i.e. values and data pointers will be \c 0, - * with the exception of FLAC__METADATA_TYPE_VORBIS_COMMENT, which will have - * the vendor string set (but zero comments). - * - * Do not pass in a value greater than or equal to - * \a FLAC__METADATA_TYPE_UNDEFINED unless you really know what you're - * doing. - * - * \param type Type of object to create - * \retval FLAC__StreamMetadata* - * \c NULL if there was an error allocating memory or the type code is - * greater than FLAC__MAX_METADATA_TYPE_CODE, else the new instance. - */ -FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_new(FLAC__MetadataType type); - -/** Create a copy of an existing metadata object. - * - * The copy is a "deep" copy, i.e. dynamically allocated data within the - * object is also copied. The caller takes ownership of the new block and - * is responsible for freeing it with FLAC__metadata_object_delete(). - * - * \param object Pointer to object to copy. - * \assert - * \code object != NULL \endcode - * \retval FLAC__StreamMetadata* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_clone(const FLAC__StreamMetadata *object); - -/** Free a metadata object. Deletes the object pointed to by \a object. - * - * The delete is a "deep" delete, i.e. dynamically allocated data within the - * object is also deleted. - * - * \param object A pointer to an existing object. - * \assert - * \code object != NULL \endcode - */ -FLAC_API void FLAC__metadata_object_delete(FLAC__StreamMetadata *object); - -/** Compares two metadata objects. - * - * The compare is "deep", i.e. dynamically allocated data within the - * object is also compared. - * - * \param block1 A pointer to an existing object. - * \param block2 A pointer to an existing object. - * \assert - * \code block1 != NULL \endcode - * \code block2 != NULL \endcode - * \retval FLAC__bool - * \c true if objects are identical, else \c false. - */ -FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *block1, const FLAC__StreamMetadata *block2); - -/** Sets the application data of an APPLICATION block. - * - * If \a copy is \c true, a copy of the data is stored; otherwise, the object - * takes ownership of the pointer. The existing data will be freed if this - * function is successful, otherwise the original data will remain if \a copy - * is \c true and malloc() fails. - * - * \note It is safe to pass a const pointer to \a data if \a copy is \c true. - * - * \param object A pointer to an existing APPLICATION object. - * \param data A pointer to the data to set. - * \param length The length of \a data in bytes. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_APPLICATION \endcode - * \code (data != NULL && length > 0) || - * (data == NULL && length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, unsigned length, FLAC__bool copy); - -/** Resize the seekpoint array. - * - * If the size shrinks, elements will truncated; if it grows, new placeholder - * points will be added to the end. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param new_num_points The desired length of the array; may be \c 0. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code (object->data.seek_table.points == NULL && object->data.seek_table.num_points == 0) || - * (object->data.seek_table.points != NULL && object->data.seek_table.num_points > 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, unsigned new_num_points); - -/** Set a seekpoint in a seektable. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param point_num Index into seekpoint array to set. - * \param point The point to set. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code object->data.seek_table.num_points > point_num \endcode - */ -FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point); - -/** Insert a seekpoint into a seektable. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param point_num Index into seekpoint array to set. - * \param point The point to set. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code object->data.seek_table.num_points >= point_num \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point); - -/** Delete a seekpoint from a seektable. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param point_num Index into seekpoint array to set. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code object->data.seek_table.num_points > point_num \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, unsigned point_num); - -/** Check a seektable to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * seektable. - * - * \param object A pointer to an existing SEEKTABLE object. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if seek table is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_is_legal(const FLAC__StreamMetadata *object); - -/** Append a number of placeholder points to the end of a seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param num The number of placeholder points to append. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, unsigned num); - -/** Append a specific seek point template to the end of a seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param sample_number The sample number of the seek point template. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_point(FLAC__StreamMetadata *object, FLAC__uint64 sample_number); - -/** Append specific seek point templates to the end of a seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param sample_numbers An array of sample numbers for the seek points. - * \param num The number of seek point templates to append. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], unsigned num); - -/** Append a set of evenly-spaced seek point templates to the end of a - * seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param num The number of placeholder points to append. - * \param total_samples The total number of samples to be encoded; - * the seekpoints will be spaced approximately - * \a total_samples / \a num samples apart. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code total_samples > 0 \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, unsigned num, FLAC__uint64 total_samples); - -/** Append a set of evenly-spaced seek point templates to the end of a - * seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param samples The number of samples apart to space the placeholder - * points. The first point will be at sample \c 0, the - * second at sample \a samples, then 2*\a samples, and - * so on. As long as \a samples and \a total_samples - * are greater than \c 0, there will always be at least - * one seekpoint at sample \c 0. - * \param total_samples The total number of samples to be encoded; - * the seekpoints will be spaced - * \a samples samples apart. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code samples > 0 \endcode - * \code total_samples > 0 \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples); - -/** Sort a seek table's seek points according to the format specification, - * removing duplicates. - * - * \param object A pointer to a seek table to be sorted. - * \param compact If \c false, behaves like FLAC__format_seektable_sort(). - * If \c true, duplicates are deleted and the seek table is - * shrunk appropriately; the number of placeholder points - * present in the seek table will be the same after the call - * as before. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_sort(FLAC__StreamMetadata *object, FLAC__bool compact); - -/** Sets the vendor string in a VORBIS_COMMENT block. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param entry The entry to set the vendor string to. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); - -/** Resize the comment array. - * - * If the size shrinks, elements will truncated; if it grows, new empty - * fields will be added to the end. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param new_num_comments The desired length of the array; may be \c 0. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code (object->data.vorbis_comment.comments == NULL && object->data.vorbis_comment.num_comments == 0) || - * (object->data.vorbis_comment.comments != NULL && object->data.vorbis_comment.num_comments > 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, unsigned new_num_comments); - -/** Sets a comment in a VORBIS_COMMENT block. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param comment_num Index into comment array to set. - * \param entry The entry to set the comment to. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code comment_num < object->data.vorbis_comment.num_comments \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); - -/** Insert a comment in a VORBIS_COMMENT block at the given index. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param comment_num The index at which to insert the comment. The comments - * at and after \a comment_num move right one position. - * To append a comment to the end, set \a comment_num to - * \c object->data.vorbis_comment.num_comments . - * \param entry The comment to insert. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code object->data.vorbis_comment.num_comments >= comment_num \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); - -/** Appends a comment to a VORBIS_COMMENT block. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param entry The comment to insert. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_append_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); - -/** Replaces comments in a VORBIS_COMMENT block with a new one. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * Depending on the the value of \a all, either all or just the first comment - * whose field name(s) match the given entry's name will be replaced by the - * given entry. If no comments match, \a entry will simply be appended. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param entry The comment to insert. - * \param all If \c true, all comments whose field name matches - * \a entry's field name will be removed, and \a entry will - * be inserted at the position of the first matching - * comment. If \c false, only the first comment whose - * field name matches \a entry's field name will be - * replaced with \a entry. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_replace_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool all, FLAC__bool copy); - -/** Delete a comment in a VORBIS_COMMENT block at the given index. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param comment_num The index of the comment to delete. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code object->data.vorbis_comment.num_comments > comment_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, unsigned comment_num); - -/** Creates a Vorbis comment entry from NUL-terminated name and value strings. - * - * On return, the filled-in \a entry->entry pointer will point to malloc()ed - * memory and shall be owned by the caller. For convenience the entry will - * have a terminating NUL. - * - * \param entry A pointer to a Vorbis comment entry. The entry's - * \c entry pointer should not point to allocated - * memory as it will be overwritten. - * \param field_name The field name in ASCII, \c NUL terminated. - * \param field_value The field value in UTF-8, \c NUL terminated. - * \assert - * \code entry != NULL \endcode - * \code field_name != NULL \endcode - * \code field_value != NULL \endcode - * \retval FLAC__bool - * \c false if malloc() fails, or if \a field_name or \a field_value does - * not comply with the Vorbis comment specification, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *field_name, const char *field_value); - -/** Splits a Vorbis comment entry into NUL-terminated name and value strings. - * - * The returned pointers to name and value will be allocated by malloc() - * and shall be owned by the caller. - * - * \param entry An existing Vorbis comment entry. - * \param field_name The address of where the returned pointer to the - * field name will be stored. - * \param field_value The address of where the returned pointer to the - * field value will be stored. - * \assert - * \code (entry.entry != NULL && entry.length > 0) \endcode - * \code memchr(entry.entry, '=', entry.length) != NULL \endcode - * \code field_name != NULL \endcode - * \code field_value != NULL \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(const FLAC__StreamMetadata_VorbisComment_Entry entry, char **field_name, char **field_value); - -/** Check if the given Vorbis comment entry's field name matches the given - * field name. - * - * \param entry An existing Vorbis comment entry. - * \param field_name The field name to check. - * \param field_name_length The length of \a field_name, not including the - * terminating \c NUL. - * \assert - * \code (entry.entry != NULL && entry.length > 0) \endcode - * \retval FLAC__bool - * \c true if the field names match, else \c false - */ -FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, unsigned field_name_length); - -/** Find a Vorbis comment with the given field name. - * - * The search begins at entry number \a offset; use an offset of 0 to - * search from the beginning of the comment array. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param offset The offset into the comment array from where to start - * the search. - * \param field_name The field name of the comment to find. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code field_name != NULL \endcode - * \retval int - * The offset in the comment array of the first comment whose field - * name matches \a field_name, or \c -1 if no match was found. - */ -FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name); - -/** Remove first Vorbis comment matching the given field name. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param field_name The field name of comment to delete. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \retval int - * \c -1 for memory allocation error, \c 0 for no matching entries, - * \c 1 for one matching entry deleted. - */ -FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entry_matching(FLAC__StreamMetadata *object, const char *field_name); - -/** Remove all Vorbis comments matching the given field name. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param field_name The field name of comments to delete. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \retval int - * \c -1 for memory allocation error, \c 0 for no matching entries, - * else the number of matching entries deleted. - */ -FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__StreamMetadata *object, const char *field_name); - -/** Create a new CUESHEET track instance. - * - * The object will be "empty"; i.e. values and data pointers will be \c 0. - * - * \retval FLAC__StreamMetadata_CueSheet_Track* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void); - -/** Create a copy of an existing CUESHEET track object. - * - * The copy is a "deep" copy, i.e. dynamically allocated data within the - * object is also copied. The caller takes ownership of the new object and - * is responsible for freeing it with - * FLAC__metadata_object_cuesheet_track_delete(). - * - * \param object Pointer to object to copy. - * \assert - * \code object != NULL \endcode - * \retval FLAC__StreamMetadata_CueSheet_Track* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_clone(const FLAC__StreamMetadata_CueSheet_Track *object); - -/** Delete a CUESHEET track object - * - * \param object A pointer to an existing CUESHEET track object. - * \assert - * \code object != NULL \endcode - */ -FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_CueSheet_Track *object); - -/** Resize a track's index point array. - * - * If the size shrinks, elements will truncated; if it grows, new blank - * indices will be added to the end. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index of the track to modify. NOTE: this is not - * necessarily the same as the track's \a number field. - * \param new_num_indices The desired length of the array; may be \c 0. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \code (object->data.cue_sheet.tracks[track_num].indices == NULL && object->data.cue_sheet.tracks[track_num].num_indices == 0) || - * (object->data.cue_sheet.tracks[track_num].indices != NULL && object->data.cue_sheet.tracks[track_num].num_indices > 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices); - -/** Insert an index point in a CUESHEET track at the given index. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index of the track to modify. NOTE: this is not - * necessarily the same as the track's \a number field. - * \param index_num The index into the track's index array at which to - * insert the index point. NOTE: this is not necessarily - * the same as the index point's \a number field. The - * indices at and after \a index_num move right one - * position. To append an index point to the end, set - * \a index_num to - * \c object->data.cue_sheet.tracks[track_num].num_indices . - * \param index The index point to insert. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \code object->data.cue_sheet.tracks[track_num].num_indices >= index_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index); - -/** Insert a blank index point in a CUESHEET track at the given index. - * - * A blank index point is one in which all field values are zero. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index of the track to modify. NOTE: this is not - * necessarily the same as the track's \a number field. - * \param index_num The index into the track's index array at which to - * insert the index point. NOTE: this is not necessarily - * the same as the index point's \a number field. The - * indices at and after \a index_num move right one - * position. To append an index point to the end, set - * \a index_num to - * \c object->data.cue_sheet.tracks[track_num].num_indices . - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \code object->data.cue_sheet.tracks[track_num].num_indices >= index_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num); - -/** Delete an index point in a CUESHEET track at the given index. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index into the track array of the track to - * modify. NOTE: this is not necessarily the same - * as the track's \a number field. - * \param index_num The index into the track's index array of the index - * to delete. NOTE: this is not necessarily the same - * as the index's \a number field. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \code object->data.cue_sheet.tracks[track_num].num_indices > index_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num); - -/** Resize the track array. - * - * If the size shrinks, elements will truncated; if it grows, new blank - * tracks will be added to the end. - * - * \param object A pointer to an existing CUESHEET object. - * \param new_num_tracks The desired length of the array; may be \c 0. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code (object->data.cue_sheet.tracks == NULL && object->data.cue_sheet.num_tracks == 0) || - * (object->data.cue_sheet.tracks != NULL && object->data.cue_sheet.num_tracks > 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks); - -/** Sets a track in a CUESHEET block. - * - * If \a copy is \c true, a copy of the track is stored; otherwise, the object - * takes ownership of the \a track pointer. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num Index into track array to set. NOTE: this is not - * necessarily the same as the track's \a number field. - * \param track The track to set the track to. You may safely pass in - * a const pointer if \a copy is \c true. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code track_num < object->data.cue_sheet.num_tracks \endcode - * \code (track->indices != NULL && track->num_indices > 0) || - * (track->indices == NULL && track->num_indices == 0) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy); - -/** Insert a track in a CUESHEET block at the given index. - * - * If \a copy is \c true, a copy of the track is stored; otherwise, the object - * takes ownership of the \a track pointer. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index at which to insert the track. NOTE: this - * is not necessarily the same as the track's \a number - * field. The tracks at and after \a track_num move right - * one position. To append a track to the end, set - * \a track_num to \c object->data.cue_sheet.num_tracks . - * \param track The track to insert. You may safely pass in a const - * pointer if \a copy is \c true. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks >= track_num \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy); - -/** Insert a blank track in a CUESHEET block at the given index. - * - * A blank track is one in which all field values are zero. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index at which to insert the track. NOTE: this - * is not necessarily the same as the track's \a number - * field. The tracks at and after \a track_num move right - * one position. To append a track to the end, set - * \a track_num to \c object->data.cue_sheet.num_tracks . - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks >= track_num \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, unsigned track_num); - -/** Delete a track in a CUESHEET block at the given index. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index into the track array of the track to - * delete. NOTE: this is not necessarily the same - * as the track's \a number field. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num); - -/** Check a cue sheet to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * cue sheet. - * - * \param object A pointer to an existing CUESHEET object. - * \param check_cd_da_subset If \c true, check CUESHEET against more - * stringent requirements for a CD-DA (audio) disc. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \retval FLAC__bool - * \c false if cue sheet is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_is_legal(const FLAC__StreamMetadata *object, FLAC__bool check_cd_da_subset, const char **violation); - -/** Calculate and return the CDDB/freedb ID for a cue sheet. The function - * assumes the cue sheet corresponds to a CD; the result is undefined - * if the cuesheet's is_cd bit is not set. - * - * \param object A pointer to an existing CUESHEET object. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \retval FLAC__uint32 - * The unsigned integer representation of the CDDB/freedb ID - */ -FLAC_API FLAC__uint32 FLAC__metadata_object_cuesheet_calculate_cddb_id(const FLAC__StreamMetadata *object); - -/** Sets the MIME type of a PICTURE block. - * - * If \a copy is \c true, a copy of the string is stored; otherwise, the object - * takes ownership of the pointer. The existing string will be freed if this - * function is successful, otherwise the original string will remain if \a copy - * is \c true and malloc() fails. - * - * \note It is safe to pass a const pointer to \a mime_type if \a copy is \c true. - * - * \param object A pointer to an existing PICTURE object. - * \param mime_type A pointer to the MIME type string. The string must be - * ASCII characters 0x20-0x7e, NUL-terminated. No validation - * is done. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode - * \code (mime_type != NULL) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy); - -/** Sets the description of a PICTURE block. - * - * If \a copy is \c true, a copy of the string is stored; otherwise, the object - * takes ownership of the pointer. The existing string will be freed if this - * function is successful, otherwise the original string will remain if \a copy - * is \c true and malloc() fails. - * - * \note It is safe to pass a const pointer to \a description if \a copy is \c true. - * - * \param object A pointer to an existing PICTURE object. - * \param description A pointer to the description string. The string must be - * valid UTF-8, NUL-terminated. No validation is done. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode - * \code (description != NULL) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy); - -/** Sets the picture data of a PICTURE block. - * - * If \a copy is \c true, a copy of the data is stored; otherwise, the object - * takes ownership of the pointer. Also sets the \a data_length field of the - * metadata object to what is passed in as the \a length parameter. The - * existing data will be freed if this function is successful, otherwise the - * original data and data_length will remain if \a copy is \c true and - * malloc() fails. - * - * \note It is safe to pass a const pointer to \a data if \a copy is \c true. - * - * \param object A pointer to an existing PICTURE object. - * \param data A pointer to the data to set. - * \param length The length of \a data in bytes. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode - * \code (data != NULL && length > 0) || - * (data == NULL && length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy); - -/** Check a PICTURE block to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * PICTURE block. - * - * \param object A pointer to existing PICTURE block to be checked. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode - * \retval FLAC__bool - * \c false if PICTURE block is illegal, else \c true. - */ -FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation); - -/* \} */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/Windows/include/FLAC/ordinals.h b/platform/Windows/include/FLAC/ordinals.h deleted file mode 100644 index a05729973..000000000 --- a/platform/Windows/include/FLAC/ordinals.h +++ /dev/null @@ -1,86 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__ORDINALS_H -#define FLAC__ORDINALS_H - -#if defined(_MSC_VER) && _MSC_VER < 1600 - -/* Microsoft Visual Studio earlier than the 2010 version did not provide - * the 1999 ISO C Standard header file . - */ - -typedef __int8 FLAC__int8; -typedef unsigned __int8 FLAC__uint8; - -typedef __int16 FLAC__int16; -typedef __int32 FLAC__int32; -typedef __int64 FLAC__int64; -typedef unsigned __int16 FLAC__uint16; -typedef unsigned __int32 FLAC__uint32; -typedef unsigned __int64 FLAC__uint64; - -#else - -/* For MSVC 2010 and everything else which provides . */ - -#include - -typedef int8_t FLAC__int8; -typedef uint8_t FLAC__uint8; - -typedef int16_t FLAC__int16; -typedef int32_t FLAC__int32; -typedef int64_t FLAC__int64; -typedef uint16_t FLAC__uint16; -typedef uint32_t FLAC__uint32; -typedef uint64_t FLAC__uint64; - -#endif - -typedef int FLAC__bool; - -typedef FLAC__uint8 FLAC__byte; - - -#ifdef true -#undef true -#endif -#ifdef false -#undef false -#endif -#ifndef __cplusplus -#define true 1 -#define false 0 -#endif - -#endif diff --git a/platform/Windows/include/FLAC/stream_decoder.h b/platform/Windows/include/FLAC/stream_decoder.h deleted file mode 100644 index 152643fcb..000000000 --- a/platform/Windows/include/FLAC/stream_decoder.h +++ /dev/null @@ -1,1560 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__STREAM_DECODER_H -#define FLAC__STREAM_DECODER_H - -#include /* for FILE */ -#include "export.h" -#include "format.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** \file include/FLAC/stream_decoder.h - * - * \brief - * This module contains the functions which implement the stream - * decoder. - * - * See the detailed documentation in the - * \link flac_stream_decoder stream decoder \endlink module. - */ - -/** \defgroup flac_decoder FLAC/ \*_decoder.h: decoder interfaces - * \ingroup flac - * - * \brief - * This module describes the decoder layers provided by libFLAC. - * - * The stream decoder can be used to decode complete streams either from - * the client via callbacks, or directly from a file, depending on how - * it is initialized. When decoding via callbacks, the client provides - * callbacks for reading FLAC data and writing decoded samples, and - * handling metadata and errors. If the client also supplies seek-related - * callback, the decoder function for sample-accurate seeking within the - * FLAC input is also available. When decoding from a file, the client - * needs only supply a filename or open \c FILE* and write/metadata/error - * callbacks; the rest of the callbacks are supplied internally. For more - * info see the \link flac_stream_decoder stream decoder \endlink module. - */ - -/** \defgroup flac_stream_decoder FLAC/stream_decoder.h: stream decoder interface - * \ingroup flac_decoder - * - * \brief - * This module contains the functions which implement the stream - * decoder. - * - * The stream decoder can decode native FLAC, and optionally Ogg FLAC - * (check FLAC_API_SUPPORTS_OGG_FLAC) streams and files. - * - * The basic usage of this decoder is as follows: - * - The program creates an instance of a decoder using - * FLAC__stream_decoder_new(). - * - The program overrides the default settings using - * FLAC__stream_decoder_set_*() functions. - * - The program initializes the instance to validate the settings and - * prepare for decoding using - * - FLAC__stream_decoder_init_stream() or FLAC__stream_decoder_init_FILE() - * or FLAC__stream_decoder_init_file() for native FLAC, - * - FLAC__stream_decoder_init_ogg_stream() or FLAC__stream_decoder_init_ogg_FILE() - * or FLAC__stream_decoder_init_ogg_file() for Ogg FLAC - * - The program calls the FLAC__stream_decoder_process_*() functions - * to decode data, which subsequently calls the callbacks. - * - The program finishes the decoding with FLAC__stream_decoder_finish(), - * which flushes the input and output and resets the decoder to the - * uninitialized state. - * - The instance may be used again or deleted with - * FLAC__stream_decoder_delete(). - * - * In more detail, the program will create a new instance by calling - * FLAC__stream_decoder_new(), then call FLAC__stream_decoder_set_*() - * functions to override the default decoder options, and call - * one of the FLAC__stream_decoder_init_*() functions. - * - * There are three initialization functions for native FLAC, one for - * setting up the decoder to decode FLAC data from the client via - * callbacks, and two for decoding directly from a FLAC file. - * - * For decoding via callbacks, use FLAC__stream_decoder_init_stream(). - * You must also supply several callbacks for handling I/O. Some (like - * seeking) are optional, depending on the capabilities of the input. - * - * For decoding directly from a file, use FLAC__stream_decoder_init_FILE() - * or FLAC__stream_decoder_init_file(). Then you must only supply an open - * \c FILE* or filename and fewer callbacks; the decoder will handle - * the other callbacks internally. - * - * There are three similarly-named init functions for decoding from Ogg - * FLAC streams. Check \c FLAC_API_SUPPORTS_OGG_FLAC to find out if the - * library has been built with Ogg support. - * - * Once the decoder is initialized, your program will call one of several - * functions to start the decoding process: - * - * - FLAC__stream_decoder_process_single() - Tells the decoder to process at - * most one metadata block or audio frame and return, calling either the - * metadata callback or write callback, respectively, once. If the decoder - * loses sync it will return with only the error callback being called. - * - FLAC__stream_decoder_process_until_end_of_metadata() - Tells the decoder - * to process the stream from the current location and stop upon reaching - * the first audio frame. The client will get one metadata, write, or error - * callback per metadata block, audio frame, or sync error, respectively. - * - FLAC__stream_decoder_process_until_end_of_stream() - Tells the decoder - * to process the stream from the current location until the read callback - * returns FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM or - * FLAC__STREAM_DECODER_READ_STATUS_ABORT. The client will get one metadata, - * write, or error callback per metadata block, audio frame, or sync error, - * respectively. - * - * When the decoder has finished decoding (normally or through an abort), - * the instance is finished by calling FLAC__stream_decoder_finish(), which - * ensures the decoder is in the correct state and frees memory. Then the - * instance may be deleted with FLAC__stream_decoder_delete() or initialized - * again to decode another stream. - * - * Seeking is exposed through the FLAC__stream_decoder_seek_absolute() method. - * At any point after the stream decoder has been initialized, the client can - * call this function to seek to an exact sample within the stream. - * Subsequently, the first time the write callback is called it will be - * passed a (possibly partial) block starting at that sample. - * - * If the client cannot seek via the callback interface provided, but still - * has another way of seeking, it can flush the decoder using - * FLAC__stream_decoder_flush() and start feeding data from the new position - * through the read callback. - * - * The stream decoder also provides MD5 signature checking. If this is - * turned on before initialization, FLAC__stream_decoder_finish() will - * report when the decoded MD5 signature does not match the one stored - * in the STREAMINFO block. MD5 checking is automatically turned off - * (until the next FLAC__stream_decoder_reset()) if there is no signature - * in the STREAMINFO block or when a seek is attempted. - * - * The FLAC__stream_decoder_set_metadata_*() functions deserve special - * attention. By default, the decoder only calls the metadata_callback for - * the STREAMINFO block. These functions allow you to tell the decoder - * explicitly which blocks to parse and return via the metadata_callback - * and/or which to skip. Use a FLAC__stream_decoder_set_metadata_respond_all(), - * FLAC__stream_decoder_set_metadata_ignore() ... or FLAC__stream_decoder_set_metadata_ignore_all(), - * FLAC__stream_decoder_set_metadata_respond() ... sequence to exactly specify - * which blocks to return. Remember that metadata blocks can potentially - * be big (for example, cover art) so filtering out the ones you don't - * use can reduce the memory requirements of the decoder. Also note the - * special forms FLAC__stream_decoder_set_metadata_respond_application(id) - * and FLAC__stream_decoder_set_metadata_ignore_application(id) for - * filtering APPLICATION blocks based on the application ID. - * - * STREAMINFO and SEEKTABLE blocks are always parsed and used internally, but - * they still can legally be filtered from the metadata_callback. - * - * \note - * The "set" functions may only be called when the decoder is in the - * state FLAC__STREAM_DECODER_UNINITIALIZED, i.e. after - * FLAC__stream_decoder_new() or FLAC__stream_decoder_finish(), but - * before FLAC__stream_decoder_init_*(). If this is the case they will - * return \c true, otherwise \c false. - * - * \note - * FLAC__stream_decoder_finish() resets all settings to the constructor - * defaults, including the callbacks. - * - * \{ - */ - - -/** State values for a FLAC__StreamDecoder - * - * The decoder's state can be obtained by calling FLAC__stream_decoder_get_state(). - */ -typedef enum { - - FLAC__STREAM_DECODER_SEARCH_FOR_METADATA = 0, - /**< The decoder is ready to search for metadata. */ - - FLAC__STREAM_DECODER_READ_METADATA, - /**< The decoder is ready to or is in the process of reading metadata. */ - - FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC, - /**< The decoder is ready to or is in the process of searching for the - * frame sync code. - */ - - FLAC__STREAM_DECODER_READ_FRAME, - /**< The decoder is ready to or is in the process of reading a frame. */ - - FLAC__STREAM_DECODER_END_OF_STREAM, - /**< The decoder has reached the end of the stream. */ - - FLAC__STREAM_DECODER_OGG_ERROR, - /**< An error occurred in the underlying Ogg layer. */ - - FLAC__STREAM_DECODER_SEEK_ERROR, - /**< An error occurred while seeking. The decoder must be flushed - * with FLAC__stream_decoder_flush() or reset with - * FLAC__stream_decoder_reset() before decoding can continue. - */ - - FLAC__STREAM_DECODER_ABORTED, - /**< The decoder was aborted by the read callback. */ - - FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR, - /**< An error occurred allocating memory. The decoder is in an invalid - * state and can no longer be used. - */ - - FLAC__STREAM_DECODER_UNINITIALIZED - /**< The decoder is in the uninitialized state; one of the - * FLAC__stream_decoder_init_*() functions must be called before samples - * can be processed. - */ - -} FLAC__StreamDecoderState; - -/** Maps a FLAC__StreamDecoderState to a C string. - * - * Using a FLAC__StreamDecoderState as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderStateString[]; - - -/** Possible return values for the FLAC__stream_decoder_init_*() functions. - */ -typedef enum { - - FLAC__STREAM_DECODER_INIT_STATUS_OK = 0, - /**< Initialization was successful. */ - - FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER, - /**< The library was not compiled with support for the given container - * format. - */ - - FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS, - /**< A required callback was not supplied. */ - - FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR, - /**< An error occurred allocating memory. */ - - FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE, - /**< fopen() failed in FLAC__stream_decoder_init_file() or - * FLAC__stream_decoder_init_ogg_file(). */ - - FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED - /**< FLAC__stream_decoder_init_*() was called when the decoder was - * already initialized, usually because - * FLAC__stream_decoder_finish() was not called. - */ - -} FLAC__StreamDecoderInitStatus; - -/** Maps a FLAC__StreamDecoderInitStatus to a C string. - * - * Using a FLAC__StreamDecoderInitStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderInitStatusString[]; - - -/** Return values for the FLAC__StreamDecoder read callback. - */ -typedef enum { - - FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, - /**< The read was OK and decoding can continue. */ - - FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM, - /**< The read was attempted while at the end of the stream. Note that - * the client must only return this value when the read callback was - * called when already at the end of the stream. Otherwise, if the read - * itself moves to the end of the stream, the client should still return - * the data and \c FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, and then on - * the next read callback it should return - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM with a byte count - * of \c 0. - */ - - FLAC__STREAM_DECODER_READ_STATUS_ABORT - /**< An unrecoverable error occurred. The decoder will return from the process call. */ - -} FLAC__StreamDecoderReadStatus; - -/** Maps a FLAC__StreamDecoderReadStatus to a C string. - * - * Using a FLAC__StreamDecoderReadStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderReadStatusString[]; - - -/** Return values for the FLAC__StreamDecoder seek callback. - */ -typedef enum { - - FLAC__STREAM_DECODER_SEEK_STATUS_OK, - /**< The seek was OK and decoding can continue. */ - - FLAC__STREAM_DECODER_SEEK_STATUS_ERROR, - /**< An unrecoverable error occurred. The decoder will return from the process call. */ - - FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED - /**< Client does not support seeking. */ - -} FLAC__StreamDecoderSeekStatus; - -/** Maps a FLAC__StreamDecoderSeekStatus to a C string. - * - * Using a FLAC__StreamDecoderSeekStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderSeekStatusString[]; - - -/** Return values for the FLAC__StreamDecoder tell callback. - */ -typedef enum { - - FLAC__STREAM_DECODER_TELL_STATUS_OK, - /**< The tell was OK and decoding can continue. */ - - FLAC__STREAM_DECODER_TELL_STATUS_ERROR, - /**< An unrecoverable error occurred. The decoder will return from the process call. */ - - FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED - /**< Client does not support telling the position. */ - -} FLAC__StreamDecoderTellStatus; - -/** Maps a FLAC__StreamDecoderTellStatus to a C string. - * - * Using a FLAC__StreamDecoderTellStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderTellStatusString[]; - - -/** Return values for the FLAC__StreamDecoder length callback. - */ -typedef enum { - - FLAC__STREAM_DECODER_LENGTH_STATUS_OK, - /**< The length call was OK and decoding can continue. */ - - FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR, - /**< An unrecoverable error occurred. The decoder will return from the process call. */ - - FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED - /**< Client does not support reporting the length. */ - -} FLAC__StreamDecoderLengthStatus; - -/** Maps a FLAC__StreamDecoderLengthStatus to a C string. - * - * Using a FLAC__StreamDecoderLengthStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderLengthStatusString[]; - - -/** Return values for the FLAC__StreamDecoder write callback. - */ -typedef enum { - - FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE, - /**< The write was OK and decoding can continue. */ - - FLAC__STREAM_DECODER_WRITE_STATUS_ABORT - /**< An unrecoverable error occurred. The decoder will return from the process call. */ - -} FLAC__StreamDecoderWriteStatus; - -/** Maps a FLAC__StreamDecoderWriteStatus to a C string. - * - * Using a FLAC__StreamDecoderWriteStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[]; - - -/** Possible values passed back to the FLAC__StreamDecoder error callback. - * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC is the generic catch- - * all. The rest could be caused by bad sync (false synchronization on - * data that is not the start of a frame) or corrupted data. The error - * itself is the decoder's best guess at what happened assuming a correct - * sync. For example \c FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER - * could be caused by a correct sync on the start of a frame, but some - * data in the frame header was corrupted. Or it could be the result of - * syncing on a point the stream that looked like the starting of a frame - * but was not. \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM - * could be because the decoder encountered a valid frame made by a future - * version of the encoder which it cannot parse, or because of a false - * sync making it appear as though an encountered frame was generated by - * a future encoder. - */ -typedef enum { - - FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, - /**< An error in the stream caused the decoder to lose synchronization. */ - - FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, - /**< The decoder encountered a corrupted frame header. */ - - FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, - /**< The frame's data did not match the CRC in the footer. */ - - FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM - /**< The decoder encountered reserved fields in use in the stream. */ - -} FLAC__StreamDecoderErrorStatus; - -/** Maps a FLAC__StreamDecoderErrorStatus to a C string. - * - * Using a FLAC__StreamDecoderErrorStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[]; - - -/*********************************************************************** - * - * class FLAC__StreamDecoder - * - ***********************************************************************/ - -struct FLAC__StreamDecoderProtected; -struct FLAC__StreamDecoderPrivate; -/** The opaque structure definition for the stream decoder type. - * See the \link flac_stream_decoder stream decoder module \endlink - * for a detailed description. - */ -typedef struct { - struct FLAC__StreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */ - struct FLAC__StreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */ -} FLAC__StreamDecoder; - -/** Signature for the read callback. - * - * A function pointer matching this signature must be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder needs more input data. The address of the - * buffer to be filled is supplied, along with the number of bytes the - * buffer can hold. The callback may choose to supply less data and - * modify the byte count but must be careful not to overflow the buffer. - * The callback then returns a status code chosen from - * FLAC__StreamDecoderReadStatus. - * - * Here is an example of a read callback for stdio streams: - * \code - * FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * if(*bytes > 0) { - * *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file); - * if(ferror(file)) - * return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - * else if(*bytes == 0) - * return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - * else - * return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; - * } - * else - * return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param buffer A pointer to a location for the callee to store - * data to be decoded. - * \param bytes A pointer to the size of the buffer. On entry - * to the callback, it contains the maximum number - * of bytes that may be stored in \a buffer. The - * callee must set it to the actual number of bytes - * stored (0 in case of error or end-of-stream) before - * returning. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderReadStatus - * The callee's return status. Note that the callback should return - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM if and only if - * zero bytes were read and there is no more data to be read. - */ -typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); - -/** Signature for the seek callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder needs to seek the input stream. The decoder - * will pass the absolute byte offset to seek to, 0 meaning the - * beginning of the stream. - * - * Here is an example of a seek callback for stdio streams: - * \code - * FLAC__StreamDecoderSeekStatus seek_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * if(file == stdin) - * return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; - * else if(fseeko(file, (off_t)absolute_byte_offset, SEEK_SET) < 0) - * return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; - * else - * return FLAC__STREAM_DECODER_SEEK_STATUS_OK; - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param absolute_byte_offset The offset from the beginning of the stream - * to seek to. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderSeekStatus - * The callee's return status. - */ -typedef FLAC__StreamDecoderSeekStatus (*FLAC__StreamDecoderSeekCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); - -/** Signature for the tell callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder wants to know the current position of the - * stream. The callback should return the byte offset from the - * beginning of the stream. - * - * Here is an example of a tell callback for stdio streams: - * \code - * FLAC__StreamDecoderTellStatus tell_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * off_t pos; - * if(file == stdin) - * return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED; - * else if((pos = ftello(file)) < 0) - * return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; - * else { - * *absolute_byte_offset = (FLAC__uint64)pos; - * return FLAC__STREAM_DECODER_TELL_STATUS_OK; - * } - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param absolute_byte_offset A pointer to storage for the current offset - * from the beginning of the stream. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderTellStatus - * The callee's return status. - */ -typedef FLAC__StreamDecoderTellStatus (*FLAC__StreamDecoderTellCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); - -/** Signature for the length callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder wants to know the total length of the stream - * in bytes. - * - * Here is an example of a length callback for stdio streams: - * \code - * FLAC__StreamDecoderLengthStatus length_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * struct stat filestats; - * - * if(file == stdin) - * return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; - * else if(fstat(fileno(file), &filestats) != 0) - * return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; - * else { - * *stream_length = (FLAC__uint64)filestats.st_size; - * return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; - * } - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param stream_length A pointer to storage for the length of the stream - * in bytes. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderLengthStatus - * The callee's return status. - */ -typedef FLAC__StreamDecoderLengthStatus (*FLAC__StreamDecoderLengthCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); - -/** Signature for the EOF callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder needs to know if the end of the stream has - * been reached. - * - * Here is an example of a EOF callback for stdio streams: - * FLAC__bool eof_cb(const FLAC__StreamDecoder *decoder, void *client_data) - * \code - * { - * FILE *file = ((MyClientData*)client_data)->file; - * return feof(file)? true : false; - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__bool - * \c true if the currently at the end of the stream, else \c false. - */ -typedef FLAC__bool (*FLAC__StreamDecoderEofCallback)(const FLAC__StreamDecoder *decoder, void *client_data); - -/** Signature for the write callback. - * - * A function pointer matching this signature must be passed to one of - * the FLAC__stream_decoder_init_*() functions. - * The supplied function will be called when the decoder has decoded a - * single audio frame. The decoder will pass the frame metadata as well - * as an array of pointers (one for each channel) pointing to the - * decoded audio. - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param frame The description of the decoded frame. See - * FLAC__Frame. - * \param buffer An array of pointers to decoded channels of data. - * Each pointer will point to an array of signed - * samples of length \a frame->header.blocksize. - * Channels will be ordered according to the FLAC - * specification; see the documentation for the - * frame header. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderWriteStatus - * The callee's return status. - */ -typedef FLAC__StreamDecoderWriteStatus (*FLAC__StreamDecoderWriteCallback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); - -/** Signature for the metadata callback. - * - * A function pointer matching this signature must be passed to one of - * the FLAC__stream_decoder_init_*() functions. - * The supplied function will be called when the decoder has decoded a - * metadata block. In a valid FLAC file there will always be one - * \c STREAMINFO block, followed by zero or more other metadata blocks. - * These will be supplied by the decoder in the same order as they - * appear in the stream and always before the first audio frame (i.e. - * write callback). The metadata block that is passed in must not be - * modified, and it doesn't live beyond the callback, so you should make - * a copy of it with FLAC__metadata_object_clone() if you will need it - * elsewhere. Since metadata blocks can potentially be large, by - * default the decoder only calls the metadata callback for the - * \c STREAMINFO block; you can instruct the decoder to pass or filter - * other blocks with FLAC__stream_decoder_set_metadata_*() calls. - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param metadata The decoded metadata block. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - */ -typedef void (*FLAC__StreamDecoderMetadataCallback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); - -/** Signature for the error callback. - * - * A function pointer matching this signature must be passed to one of - * the FLAC__stream_decoder_init_*() functions. - * The supplied function will be called whenever an error occurs during - * decoding. - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param status The error encountered by the decoder. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - */ -typedef void (*FLAC__StreamDecoderErrorCallback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); - - -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -/** Create a new stream decoder instance. The instance is created with - * default settings; see the individual FLAC__stream_decoder_set_*() - * functions for each setting's default. - * - * \retval FLAC__StreamDecoder* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void); - -/** Free a decoder instance. Deletes the object pointed to by \a decoder. - * - * \param decoder A pointer to an existing decoder. - * \assert - * \code decoder != NULL \endcode - */ -FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder); - - -/*********************************************************************** - * - * Public class method prototypes - * - ***********************************************************************/ - -/** Set the serial number for the FLAC stream within the Ogg container. - * The default behavior is to use the serial number of the first Ogg - * page. Setting a serial number here will explicitly specify which - * stream is to be decoded. - * - * \note - * This does not need to be set for native FLAC decoding. - * - * \default \c use serial number of first page - * \param decoder A decoder instance to set. - * \param serial_number See above. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_ogg_serial_number(FLAC__StreamDecoder *decoder, long serial_number); - -/** Set the "MD5 signature checking" flag. If \c true, the decoder will - * compute the MD5 signature of the unencoded audio data while decoding - * and compare it to the signature from the STREAMINFO block, if it - * exists, during FLAC__stream_decoder_finish(). - * - * MD5 signature checking will be turned off (until the next - * FLAC__stream_decoder_reset()) if there is no signature in the - * STREAMINFO block or when a seek is attempted. - * - * Clients that do not use the MD5 check should leave this off to speed - * up decoding. - * - * \default \c false - * \param decoder A decoder instance to set. - * \param value Flag value (see above). - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_md5_checking(FLAC__StreamDecoder *decoder, FLAC__bool value); - -/** Direct the decoder to pass on all metadata blocks of type \a type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param type See above. - * \assert - * \code decoder != NULL \endcode - * \a type is valid - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); - -/** Direct the decoder to pass on all APPLICATION metadata blocks of the - * given \a id. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param id See above. - * \assert - * \code decoder != NULL \endcode - * \code id != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); - -/** Direct the decoder to pass on all metadata blocks of any type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder); - -/** Direct the decoder to filter out all metadata blocks of type \a type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param type See above. - * \assert - * \code decoder != NULL \endcode - * \a type is valid - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); - -/** Direct the decoder to filter out all APPLICATION metadata blocks of - * the given \a id. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param id See above. - * \assert - * \code decoder != NULL \endcode - * \code id != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); - -/** Direct the decoder to filter out all metadata blocks of any type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder); - -/** Get the current decoder state. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderState - * The current decoder state. - */ -FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder); - -/** Get the current decoder state as a C string. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval const char * - * The decoder state as a C string. Do not modify the contents. - */ -FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder); - -/** Get the "MD5 signature checking" flag. - * This is the value of the setting, not whether or not the decoder is - * currently checking the MD5 (remember, it can be turned off automatically - * by a seek). When the decoder is reset the flag will be restored to the - * value returned by this function. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * See above. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDecoder *decoder); - -/** Get the total number of samples in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the \c STREAMINFO block. A value of \c 0 means "unknown". - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder); - -/** Get the current number of channels in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder); - -/** Get the current channel assignment in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__ChannelAssignment - * See above. - */ -FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder); - -/** Get the current sample resolution in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder); - -/** Get the current sample rate in Hz of the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder); - -/** Get the current blocksize of the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ -FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder); - -/** Returns the decoder's current read position within the stream. - * The position is the byte offset from the start of the stream. - * Bytes before this position have been fully decoded. Note that - * there may still be undecoded bytes in the decoder's read FIFO. - * The returned position is correct even after a seek. - * - * \warning This function currently only works for native FLAC, - * not Ogg FLAC streams. - * - * \param decoder A decoder instance to query. - * \param position Address at which to return the desired position. - * \assert - * \code decoder != NULL \endcode - * \code position != NULL \endcode - * \retval FLAC__bool - * \c true if successful, \c false if the stream is not native FLAC, - * or there was an error from the 'tell' callback or it returned - * \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position); - -/** Initialize the decoder instance to decode native FLAC streams. - * - * This flavor of initialization sets up the decoder to decode from a - * native FLAC stream. I/O is performed via callbacks to the client. - * For decoding from a plain file via filename or open FILE*, - * FLAC__stream_decoder_init_file() and FLAC__stream_decoder_init_FILE() - * provide a simpler interface. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \param decoder An uninitialized decoder instance. - * \param read_callback See FLAC__StreamDecoderReadCallback. This - * pointer must not be \c NULL. - * \param seek_callback See FLAC__StreamDecoderSeekCallback. This - * pointer may be \c NULL if seeking is not - * supported. If \a seek_callback is not \c NULL then a - * \a tell_callback, \a length_callback, and \a eof_callback must also be supplied. - * Alternatively, a dummy seek callback that just - * returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param tell_callback See FLAC__StreamDecoderTellCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a tell_callback must also be supplied. - * Alternatively, a dummy tell callback that just - * returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param length_callback See FLAC__StreamDecoderLengthCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a length_callback must also be supplied. - * Alternatively, a dummy length callback that just - * returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param eof_callback See FLAC__StreamDecoderEofCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a eof_callback must also be supplied. - * Alternatively, a dummy length callback that just - * returns \c false - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ -FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream( - FLAC__StreamDecoder *decoder, - FLAC__StreamDecoderReadCallback read_callback, - FLAC__StreamDecoderSeekCallback seek_callback, - FLAC__StreamDecoderTellCallback tell_callback, - FLAC__StreamDecoderLengthCallback length_callback, - FLAC__StreamDecoderEofCallback eof_callback, - FLAC__StreamDecoderWriteCallback write_callback, - FLAC__StreamDecoderMetadataCallback metadata_callback, - FLAC__StreamDecoderErrorCallback error_callback, - void *client_data -); - -/** Initialize the decoder instance to decode Ogg FLAC streams. - * - * This flavor of initialization sets up the decoder to decode from a - * FLAC stream in an Ogg container. I/O is performed via callbacks to the - * client. For decoding from a plain file via filename or open FILE*, - * FLAC__stream_decoder_init_ogg_file() and FLAC__stream_decoder_init_ogg_FILE() - * provide a simpler interface. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \note Support for Ogg FLAC in the library is optional. If this - * library has been built without support for Ogg FLAC, this function - * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. - * - * \param decoder An uninitialized decoder instance. - * \param read_callback See FLAC__StreamDecoderReadCallback. This - * pointer must not be \c NULL. - * \param seek_callback See FLAC__StreamDecoderSeekCallback. This - * pointer may be \c NULL if seeking is not - * supported. If \a seek_callback is not \c NULL then a - * \a tell_callback, \a length_callback, and \a eof_callback must also be supplied. - * Alternatively, a dummy seek callback that just - * returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param tell_callback See FLAC__StreamDecoderTellCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a tell_callback must also be supplied. - * Alternatively, a dummy tell callback that just - * returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param length_callback See FLAC__StreamDecoderLengthCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a length_callback must also be supplied. - * Alternatively, a dummy length callback that just - * returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param eof_callback See FLAC__StreamDecoderEofCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a eof_callback must also be supplied. - * Alternatively, a dummy length callback that just - * returns \c false - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ -FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream( - FLAC__StreamDecoder *decoder, - FLAC__StreamDecoderReadCallback read_callback, - FLAC__StreamDecoderSeekCallback seek_callback, - FLAC__StreamDecoderTellCallback tell_callback, - FLAC__StreamDecoderLengthCallback length_callback, - FLAC__StreamDecoderEofCallback eof_callback, - FLAC__StreamDecoderWriteCallback write_callback, - FLAC__StreamDecoderMetadataCallback metadata_callback, - FLAC__StreamDecoderErrorCallback error_callback, - void *client_data -); - -/** Initialize the decoder instance to decode native FLAC files. - * - * This flavor of initialization sets up the decoder to decode from a - * plain native FLAC file. For non-stdio streams, you must use - * FLAC__stream_decoder_init_stream() and provide callbacks for the I/O. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \param decoder An uninitialized decoder instance. - * \param file An open FLAC file. The file should have been - * opened with mode \c "rb" and rewound. The file - * becomes owned by the decoder and should not be - * manipulated by the client while decoding. - * Unless \a file is \c stdin, it will be closed - * when FLAC__stream_decoder_finish() is called. - * Note however that seeking will not work when - * decoding from \c stdout since it is not seekable. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \code file != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ -FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE( - FLAC__StreamDecoder *decoder, - FILE *file, - FLAC__StreamDecoderWriteCallback write_callback, - FLAC__StreamDecoderMetadataCallback metadata_callback, - FLAC__StreamDecoderErrorCallback error_callback, - void *client_data -); - -/** Initialize the decoder instance to decode Ogg FLAC files. - * - * This flavor of initialization sets up the decoder to decode from a - * plain Ogg FLAC file. For non-stdio streams, you must use - * FLAC__stream_decoder_init_ogg_stream() and provide callbacks for the I/O. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \note Support for Ogg FLAC in the library is optional. If this - * library has been built without support for Ogg FLAC, this function - * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. - * - * \param decoder An uninitialized decoder instance. - * \param file An open FLAC file. The file should have been - * opened with mode \c "rb" and rewound. The file - * becomes owned by the decoder and should not be - * manipulated by the client while decoding. - * Unless \a file is \c stdin, it will be closed - * when FLAC__stream_decoder_finish() is called. - * Note however that seeking will not work when - * decoding from \c stdout since it is not seekable. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \code file != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ -FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE( - FLAC__StreamDecoder *decoder, - FILE *file, - FLAC__StreamDecoderWriteCallback write_callback, - FLAC__StreamDecoderMetadataCallback metadata_callback, - FLAC__StreamDecoderErrorCallback error_callback, - void *client_data -); - -/** Initialize the decoder instance to decode native FLAC files. - * - * This flavor of initialization sets up the decoder to decode from a plain - * native FLAC file. If POSIX fopen() semantics are not sufficient, (for - * example, with Unicode filenames on Windows), you must use - * FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream() - * and provide callbacks for the I/O. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \param decoder An uninitialized decoder instance. - * \param filename The name of the file to decode from. The file will - * be opened with fopen(). Use \c NULL to decode from - * \c stdin. Note that \c stdin is not seekable. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ -FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file( - FLAC__StreamDecoder *decoder, - const char *filename, - FLAC__StreamDecoderWriteCallback write_callback, - FLAC__StreamDecoderMetadataCallback metadata_callback, - FLAC__StreamDecoderErrorCallback error_callback, - void *client_data -); - -/** Initialize the decoder instance to decode Ogg FLAC files. - * - * This flavor of initialization sets up the decoder to decode from a plain - * Ogg FLAC file. If POSIX fopen() semantics are not sufficient, (for - * example, with Unicode filenames on Windows), you must use - * FLAC__stream_decoder_init_ogg_FILE(), or FLAC__stream_decoder_init_ogg_stream() - * and provide callbacks for the I/O. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \note Support for Ogg FLAC in the library is optional. If this - * library has been built without support for Ogg FLAC, this function - * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. - * - * \param decoder An uninitialized decoder instance. - * \param filename The name of the file to decode from. The file will - * be opened with fopen(). Use \c NULL to decode from - * \c stdin. Note that \c stdin is not seekable. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ -FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_file( - FLAC__StreamDecoder *decoder, - const char *filename, - FLAC__StreamDecoderWriteCallback write_callback, - FLAC__StreamDecoderMetadataCallback metadata_callback, - FLAC__StreamDecoderErrorCallback error_callback, - void *client_data -); - -/** Finish the decoding process. - * Flushes the decoding buffer, releases resources, resets the decoder - * settings to their defaults, and returns the decoder state to - * FLAC__STREAM_DECODER_UNINITIALIZED. - * - * In the event of a prematurely-terminated decode, it is not strictly - * necessary to call this immediately before FLAC__stream_decoder_delete() - * but it is good practice to match every FLAC__stream_decoder_init_*() - * with a FLAC__stream_decoder_finish(). - * - * \param decoder An uninitialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if MD5 checking is on AND a STREAMINFO block was available - * AND the MD5 signature in the STREAMINFO block was non-zero AND the - * signature does not match the one computed by the decoder; else - * \c true. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder); - -/** Flush the stream input. - * The decoder's input buffer will be cleared and the state set to - * \c FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC. This will also turn - * off MD5 checking. - * - * \param decoder A decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false if a memory allocation - * error occurs (in which case the state will be set to - * \c FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder); - -/** Reset the decoding process. - * The decoder's input buffer will be cleared and the state set to - * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA. This is similar to - * FLAC__stream_decoder_finish() except that the settings are - * preserved; there is no need to call FLAC__stream_decoder_init_*() - * before decoding again. MD5 checking will be restored to its original - * setting. - * - * If the decoder is seekable, or was initialized with - * FLAC__stream_decoder_init*_FILE() or FLAC__stream_decoder_init*_file(), - * the decoder will also attempt to seek to the beginning of the file. - * If this rewind fails, this function will return \c false. It follows - * that FLAC__stream_decoder_reset() cannot be used when decoding from - * \c stdin. - * - * If the decoder was initialized with FLAC__stream_encoder_init*_stream() - * and is not seekable (i.e. no seek callback was provided or the seek - * callback returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED), it - * is the duty of the client to start feeding data from the beginning of - * the stream on the next FLAC__stream_decoder_process() or - * FLAC__stream_decoder_process_interleaved() call. - * - * \param decoder A decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false if a memory allocation occurs - * (in which case the state will be set to - * \c FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR) or a seek error - * occurs (the state will be unchanged). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder); - -/** Decode one metadata block or audio frame. - * This version instructs the decoder to decode a either a single metadata - * block or a single frame and stop, unless the callbacks return a fatal - * error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * As the decoder needs more input it will call the read callback. - * Depending on what was decoded, the metadata or write callback will be - * called with the decoded metadata block or audio frame. - * - * Unless there is a fatal read error or end of stream, this function - * will return once one whole frame is decoded. In other words, if the - * stream is not synchronized or points to a corrupt frame header, the - * decoder will continue to try and resync until it gets to a valid - * frame, then decode one frame, then return. If the decoder points to - * a frame whose frame CRC in the frame footer does not match the - * computed frame CRC, this function will issue a - * FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH error to the - * error callback, and return, having decoded one complete, although - * corrupt, frame. (Such corrupted frames are sent as silence of the - * correct length to the write callback.) - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any fatal read, write, or memory allocation error - * occurred (meaning decoding must stop), else \c true; for more - * information about the decoder, check the decoder state with - * FLAC__stream_decoder_get_state(). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder); - -/** Decode until the end of the metadata. - * This version instructs the decoder to decode from the current position - * and continue until all the metadata has been read, or until the - * callbacks return a fatal error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * As the decoder needs more input it will call the read callback. - * As each metadata block is decoded, the metadata callback will be called - * with the decoded metadata. - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any fatal read, write, or memory allocation error - * occurred (meaning decoding must stop), else \c true; for more - * information about the decoder, check the decoder state with - * FLAC__stream_decoder_get_state(). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder); - -/** Decode until the end of the stream. - * This version instructs the decoder to decode from the current position - * and continue until the end of stream (the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM), or until the - * callbacks return a fatal error. - * - * As the decoder needs more input it will call the read callback. - * As each metadata block and frame is decoded, the metadata or write - * callback will be called with the decoded metadata or frame. - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any fatal read, write, or memory allocation error - * occurred (meaning decoding must stop), else \c true; for more - * information about the decoder, check the decoder state with - * FLAC__stream_decoder_get_state(). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder); - -/** Skip one audio frame. - * This version instructs the decoder to 'skip' a single frame and stop, - * unless the callbacks return a fatal error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * The decoding flow is the same as what occurs when - * FLAC__stream_decoder_process_single() is called to process an audio - * frame, except that this function does not decode the parsed data into - * PCM or call the write callback. The integrity of the frame is still - * checked the same way as in the other process functions. - * - * This function will return once one whole frame is skipped, in the - * same way that FLAC__stream_decoder_process_single() will return once - * one whole frame is decoded. - * - * This function can be used in more quickly determining FLAC frame - * boundaries when decoding of the actual data is not needed, for - * example when an application is separating a FLAC stream into frames - * for editing or storing in a container. To do this, the application - * can use FLAC__stream_decoder_skip_single_frame() to quickly advance - * to the next frame, then use - * FLAC__stream_decoder_get_decode_position() to find the new frame - * boundary. - * - * This function should only be called when the stream has advanced - * past all the metadata, otherwise it will return \c false. - * - * \param decoder An initialized decoder instance not in a metadata - * state. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any fatal read, write, or memory allocation error - * occurred (meaning decoding must stop), or if the decoder - * is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or - * FLAC__STREAM_DECODER_READ_METADATA state, else \c true; for more - * information about the decoder, check the decoder state with - * FLAC__stream_decoder_get_state(). - */ -FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder); - -/** Flush the input and seek to an absolute sample. - * Decoding will resume at the given sample. Note that because of - * this, the next write callback may contain a partial block. The - * client must support seeking the input or this function will fail - * and return \c false. Furthermore, if the decoder state is - * \c FLAC__STREAM_DECODER_SEEK_ERROR, then the decoder must be flushed - * with FLAC__stream_decoder_flush() or reset with - * FLAC__stream_decoder_reset() before decoding can continue. - * - * \param decoder A decoder instance. - * \param sample The target sample number to seek to. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false. - */ -FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *decoder, FLAC__uint64 sample); - -/* \} */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/Windows/include/FLAC/stream_encoder.h b/platform/Windows/include/FLAC/stream_encoder.h deleted file mode 100644 index 6f7796bb3..000000000 --- a/platform/Windows/include/FLAC/stream_encoder.h +++ /dev/null @@ -1,1769 +0,0 @@ -/* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the Xiph.org Foundation nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef FLAC__STREAM_ENCODER_H -#define FLAC__STREAM_ENCODER_H - -#include /* for FILE */ -#include "export.h" -#include "format.h" -#include "stream_decoder.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** \file include/FLAC/stream_encoder.h - * - * \brief - * This module contains the functions which implement the stream - * encoder. - * - * See the detailed documentation in the - * \link flac_stream_encoder stream encoder \endlink module. - */ - -/** \defgroup flac_encoder FLAC/ \*_encoder.h: encoder interfaces - * \ingroup flac - * - * \brief - * This module describes the encoder layers provided by libFLAC. - * - * The stream encoder can be used to encode complete streams either to the - * client via callbacks, or directly to a file, depending on how it is - * initialized. When encoding via callbacks, the client provides a write - * callback which will be called whenever FLAC data is ready to be written. - * If the client also supplies a seek callback, the encoder will also - * automatically handle the writing back of metadata discovered while - * encoding, like stream info, seek points offsets, etc. When encoding to - * a file, the client needs only supply a filename or open \c FILE* and an - * optional progress callback for periodic notification of progress; the - * write and seek callbacks are supplied internally. For more info see the - * \link flac_stream_encoder stream encoder \endlink module. - */ - -/** \defgroup flac_stream_encoder FLAC/stream_encoder.h: stream encoder interface - * \ingroup flac_encoder - * - * \brief - * This module contains the functions which implement the stream - * encoder. - * - * The stream encoder can encode to native FLAC, and optionally Ogg FLAC - * (check FLAC_API_SUPPORTS_OGG_FLAC) streams and files. - * - * The basic usage of this encoder is as follows: - * - The program creates an instance of an encoder using - * FLAC__stream_encoder_new(). - * - The program overrides the default settings using - * FLAC__stream_encoder_set_*() functions. At a minimum, the following - * functions should be called: - * - FLAC__stream_encoder_set_channels() - * - FLAC__stream_encoder_set_bits_per_sample() - * - FLAC__stream_encoder_set_sample_rate() - * - FLAC__stream_encoder_set_ogg_serial_number() (if encoding to Ogg FLAC) - * - FLAC__stream_encoder_set_total_samples_estimate() (if known) - * - If the application wants to control the compression level or set its own - * metadata, then the following should also be called: - * - FLAC__stream_encoder_set_compression_level() - * - FLAC__stream_encoder_set_verify() - * - FLAC__stream_encoder_set_metadata() - * - The rest of the set functions should only be called if the client needs - * exact control over how the audio is compressed; thorough understanding - * of the FLAC format is necessary to achieve good results. - * - The program initializes the instance to validate the settings and - * prepare for encoding using - * - FLAC__stream_encoder_init_stream() or FLAC__stream_encoder_init_FILE() - * or FLAC__stream_encoder_init_file() for native FLAC - * - FLAC__stream_encoder_init_ogg_stream() or FLAC__stream_encoder_init_ogg_FILE() - * or FLAC__stream_encoder_init_ogg_file() for Ogg FLAC - * - The program calls FLAC__stream_encoder_process() or - * FLAC__stream_encoder_process_interleaved() to encode data, which - * subsequently calls the callbacks when there is encoder data ready - * to be written. - * - The program finishes the encoding with FLAC__stream_encoder_finish(), - * which causes the encoder to encode any data still in its input pipe, - * update the metadata with the final encoding statistics if output - * seeking is possible, and finally reset the encoder to the - * uninitialized state. - * - The instance may be used again or deleted with - * FLAC__stream_encoder_delete(). - * - * In more detail, the stream encoder functions similarly to the - * \link flac_stream_decoder stream decoder \endlink, but has fewer - * callbacks and more options. Typically the client will create a new - * instance by calling FLAC__stream_encoder_new(), then set the necessary - * parameters with FLAC__stream_encoder_set_*(), and initialize it by - * calling one of the FLAC__stream_encoder_init_*() functions. - * - * Unlike the decoders, the stream encoder has many options that can - * affect the speed and compression ratio. When setting these parameters - * you should have some basic knowledge of the format (see the - * user-level documentation - * or the formal description). The - * FLAC__stream_encoder_set_*() functions themselves do not validate the - * values as many are interdependent. The FLAC__stream_encoder_init_*() - * functions will do this, so make sure to pay attention to the state - * returned by FLAC__stream_encoder_init_*() to make sure that it is - * FLAC__STREAM_ENCODER_INIT_STATUS_OK. Any parameters that are not set - * before FLAC__stream_encoder_init_*() will take on the defaults from - * the constructor. - * - * There are three initialization functions for native FLAC, one for - * setting up the encoder to encode FLAC data to the client via - * callbacks, and two for encoding directly to a file. - * - * For encoding via callbacks, use FLAC__stream_encoder_init_stream(). - * You must also supply a write callback which will be called anytime - * there is raw encoded data to write. If the client can seek the output - * it is best to also supply seek and tell callbacks, as this allows the - * encoder to go back after encoding is finished to write back - * information that was collected while encoding, like seek point offsets, - * frame sizes, etc. - * - * For encoding directly to a file, use FLAC__stream_encoder_init_FILE() - * or FLAC__stream_encoder_init_file(). Then you must only supply a - * filename or open \c FILE*; the encoder will handle all the callbacks - * internally. You may also supply a progress callback for periodic - * notification of the encoding progress. - * - * There are three similarly-named init functions for encoding to Ogg - * FLAC streams. Check \c FLAC_API_SUPPORTS_OGG_FLAC to find out if the - * library has been built with Ogg support. - * - * The call to FLAC__stream_encoder_init_*() currently will also immediately - * call the write callback several times, once with the \c fLaC signature, - * and once for each encoded metadata block. Note that for Ogg FLAC - * encoding you will usually get at least twice the number of callbacks than - * with native FLAC, one for the Ogg page header and one for the page body. - * - * After initializing the instance, the client may feed audio data to the - * encoder in one of two ways: - * - * - Channel separate, through FLAC__stream_encoder_process() - The client - * will pass an array of pointers to buffers, one for each channel, to - * the encoder, each of the same length. The samples need not be - * block-aligned, but each channel should have the same number of samples. - * - Channel interleaved, through - * FLAC__stream_encoder_process_interleaved() - The client will pass a single - * pointer to data that is channel-interleaved (i.e. channel0_sample0, - * channel1_sample0, ... , channelN_sample0, channel0_sample1, ...). - * Again, the samples need not be block-aligned but they must be - * sample-aligned, i.e. the first value should be channel0_sample0 and - * the last value channelN_sampleM. - * - * Note that for either process call, each sample in the buffers should be a - * signed integer, right-justified to the resolution set by - * FLAC__stream_encoder_set_bits_per_sample(). For example, if the resolution - * is 16 bits per sample, the samples should all be in the range [-32768,32767]. - * - * When the client is finished encoding data, it calls - * FLAC__stream_encoder_finish(), which causes the encoder to encode any - * data still in its input pipe, and call the metadata callback with the - * final encoding statistics. Then the instance may be deleted with - * FLAC__stream_encoder_delete() or initialized again to encode another - * stream. - * - * For programs that write their own metadata, but that do not know the - * actual metadata until after encoding, it is advantageous to instruct - * the encoder to write a PADDING block of the correct size, so that - * instead of rewriting the whole stream after encoding, the program can - * just overwrite the PADDING block. If only the maximum size of the - * metadata is known, the program can write a slightly larger padding - * block, then split it after encoding. - * - * Make sure you understand how lengths are calculated. All FLAC metadata - * blocks have a 4 byte header which contains the type and length. This - * length does not include the 4 bytes of the header. See the format page - * for the specification of metadata blocks and their lengths. - * - * \note - * If you are writing the FLAC data to a file via callbacks, make sure it - * is open for update (e.g. mode "w+" for stdio streams). This is because - * after the first encoding pass, the encoder will try to seek back to the - * beginning of the stream, to the STREAMINFO block, to write some data - * there. (If using FLAC__stream_encoder_init*_file() or - * FLAC__stream_encoder_init*_FILE(), the file is managed internally.) - * - * \note - * The "set" functions may only be called when the encoder is in the - * state FLAC__STREAM_ENCODER_UNINITIALIZED, i.e. after - * FLAC__stream_encoder_new() or FLAC__stream_encoder_finish(), but - * before FLAC__stream_encoder_init_*(). If this is the case they will - * return \c true, otherwise \c false. - * - * \note - * FLAC__stream_encoder_finish() resets all settings to the constructor - * defaults. - * - * \{ - */ - - -/** State values for a FLAC__StreamEncoder. - * - * The encoder's state can be obtained by calling FLAC__stream_encoder_get_state(). - * - * If the encoder gets into any other state besides \c FLAC__STREAM_ENCODER_OK - * or \c FLAC__STREAM_ENCODER_UNINITIALIZED, it becomes invalid for encoding and - * must be deleted with FLAC__stream_encoder_delete(). - */ -typedef enum { - - FLAC__STREAM_ENCODER_OK = 0, - /**< The encoder is in the normal OK state and samples can be processed. */ - - FLAC__STREAM_ENCODER_UNINITIALIZED, - /**< The encoder is in the uninitialized state; one of the - * FLAC__stream_encoder_init_*() functions must be called before samples - * can be processed. - */ - - FLAC__STREAM_ENCODER_OGG_ERROR, - /**< An error occurred in the underlying Ogg layer. */ - - FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR, - /**< An error occurred in the underlying verify stream decoder; - * check FLAC__stream_encoder_get_verify_decoder_state(). - */ - - FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA, - /**< The verify decoder detected a mismatch between the original - * audio signal and the decoded audio signal. - */ - - FLAC__STREAM_ENCODER_CLIENT_ERROR, - /**< One of the callbacks returned a fatal error. */ - - FLAC__STREAM_ENCODER_IO_ERROR, - /**< An I/O error occurred while opening/reading/writing a file. - * Check \c errno. - */ - - FLAC__STREAM_ENCODER_FRAMING_ERROR, - /**< An error occurred while writing the stream; usually, the - * write_callback returned an error. - */ - - FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR - /**< Memory allocation failed. */ - -} FLAC__StreamEncoderState; - -/** Maps a FLAC__StreamEncoderState to a C string. - * - * Using a FLAC__StreamEncoderState as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamEncoderStateString[]; - - -/** Possible return values for the FLAC__stream_encoder_init_*() functions. - */ -typedef enum { - - FLAC__STREAM_ENCODER_INIT_STATUS_OK = 0, - /**< Initialization was successful. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR, - /**< General failure to set up encoder; call FLAC__stream_encoder_get_state() for cause. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER, - /**< The library was not compiled with support for the given container - * format. - */ - - FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS, - /**< A required callback was not supplied. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS, - /**< The encoder has an invalid setting for number of channels. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE, - /**< The encoder has an invalid setting for bits-per-sample. - * FLAC supports 4-32 bps but the reference encoder currently supports - * only up to 24 bps. - */ - - FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE, - /**< The encoder has an invalid setting for the input sample rate. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE, - /**< The encoder has an invalid setting for the block size. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER, - /**< The encoder has an invalid setting for the maximum LPC order. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION, - /**< The encoder has an invalid setting for the precision of the quantized linear predictor coefficients. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER, - /**< The specified block size is less than the maximum LPC order. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE, - /**< The encoder is bound to the Subset but other settings violate it. */ - - FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA, - /**< The metadata input to the encoder is invalid, in one of the following ways: - * - FLAC__stream_encoder_set_metadata() was called with a null pointer but a block count > 0 - * - One of the metadata blocks contains an undefined type - * - It contains an illegal CUESHEET as checked by FLAC__format_cuesheet_is_legal() - * - It contains an illegal SEEKTABLE as checked by FLAC__format_seektable_is_legal() - * - It contains more than one SEEKTABLE block or more than one VORBIS_COMMENT block - */ - - FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED - /**< FLAC__stream_encoder_init_*() was called when the encoder was - * already initialized, usually because - * FLAC__stream_encoder_finish() was not called. - */ - -} FLAC__StreamEncoderInitStatus; - -/** Maps a FLAC__StreamEncoderInitStatus to a C string. - * - * Using a FLAC__StreamEncoderInitStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamEncoderInitStatusString[]; - - -/** Return values for the FLAC__StreamEncoder read callback. - */ -typedef enum { - - FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE, - /**< The read was OK and decoding can continue. */ - - FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM, - /**< The read was attempted at the end of the stream. */ - - FLAC__STREAM_ENCODER_READ_STATUS_ABORT, - /**< An unrecoverable error occurred. */ - - FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED - /**< Client does not support reading back from the output. */ - -} FLAC__StreamEncoderReadStatus; - -/** Maps a FLAC__StreamEncoderReadStatus to a C string. - * - * Using a FLAC__StreamEncoderReadStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamEncoderReadStatusString[]; - - -/** Return values for the FLAC__StreamEncoder write callback. - */ -typedef enum { - - FLAC__STREAM_ENCODER_WRITE_STATUS_OK = 0, - /**< The write was OK and encoding can continue. */ - - FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR - /**< An unrecoverable error occurred. The encoder will return from the process call. */ - -} FLAC__StreamEncoderWriteStatus; - -/** Maps a FLAC__StreamEncoderWriteStatus to a C string. - * - * Using a FLAC__StreamEncoderWriteStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[]; - - -/** Return values for the FLAC__StreamEncoder seek callback. - */ -typedef enum { - - FLAC__STREAM_ENCODER_SEEK_STATUS_OK, - /**< The seek was OK and encoding can continue. */ - - FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR, - /**< An unrecoverable error occurred. */ - - FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED - /**< Client does not support seeking. */ - -} FLAC__StreamEncoderSeekStatus; - -/** Maps a FLAC__StreamEncoderSeekStatus to a C string. - * - * Using a FLAC__StreamEncoderSeekStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[]; - - -/** Return values for the FLAC__StreamEncoder tell callback. - */ -typedef enum { - - FLAC__STREAM_ENCODER_TELL_STATUS_OK, - /**< The tell was OK and encoding can continue. */ - - FLAC__STREAM_ENCODER_TELL_STATUS_ERROR, - /**< An unrecoverable error occurred. */ - - FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED - /**< Client does not support seeking. */ - -} FLAC__StreamEncoderTellStatus; - -/** Maps a FLAC__StreamEncoderTellStatus to a C string. - * - * Using a FLAC__StreamEncoderTellStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ -extern FLAC_API const char * const FLAC__StreamEncoderTellStatusString[]; - - -/*********************************************************************** - * - * class FLAC__StreamEncoder - * - ***********************************************************************/ - -struct FLAC__StreamEncoderProtected; -struct FLAC__StreamEncoderPrivate; -/** The opaque structure definition for the stream encoder type. - * See the \link flac_stream_encoder stream encoder module \endlink - * for a detailed description. - */ -typedef struct { - struct FLAC__StreamEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */ - struct FLAC__StreamEncoderPrivate *private_; /* avoid the C++ keyword 'private' */ -} FLAC__StreamEncoder; - -/** Signature for the read callback. - * - * A function pointer matching this signature must be passed to - * FLAC__stream_encoder_init_ogg_stream() if seeking is supported. - * The supplied function will be called when the encoder needs to read back - * encoded data. This happens during the metadata callback, when the encoder - * has to read, modify, and rewrite the metadata (e.g. seekpoints) gathered - * while encoding. The address of the buffer to be filled is supplied, along - * with the number of bytes the buffer can hold. The callback may choose to - * supply less data and modify the byte count but must be careful not to - * overflow the buffer. The callback then returns a status code chosen from - * FLAC__StreamEncoderReadStatus. - * - * Here is an example of a read callback for stdio streams: - * \code - * FLAC__StreamEncoderReadStatus read_cb(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * if(*bytes > 0) { - * *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file); - * if(ferror(file)) - * return FLAC__STREAM_ENCODER_READ_STATUS_ABORT; - * else if(*bytes == 0) - * return FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM; - * else - * return FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE; - * } - * else - * return FLAC__STREAM_ENCODER_READ_STATUS_ABORT; - * } - * \endcode - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param buffer A pointer to a location for the callee to store - * data to be encoded. - * \param bytes A pointer to the size of the buffer. On entry - * to the callback, it contains the maximum number - * of bytes that may be stored in \a buffer. The - * callee must set it to the actual number of bytes - * stored (0 in case of error or end-of-stream) before - * returning. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_set_client_data(). - * \retval FLAC__StreamEncoderReadStatus - * The callee's return status. - */ -typedef FLAC__StreamEncoderReadStatus (*FLAC__StreamEncoderReadCallback)(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data); - -/** Signature for the write callback. - * - * A function pointer matching this signature must be passed to - * FLAC__stream_encoder_init*_stream(). The supplied function will be called - * by the encoder anytime there is raw encoded data ready to write. It may - * include metadata mixed with encoded audio frames and the data is not - * guaranteed to be aligned on frame or metadata block boundaries. - * - * The only duty of the callback is to write out the \a bytes worth of data - * in \a buffer to the current position in the output stream. The arguments - * \a samples and \a current_frame are purely informational. If \a samples - * is greater than \c 0, then \a current_frame will hold the current frame - * number that is being written; otherwise it indicates that the write - * callback is being called to write metadata. - * - * \note - * Unlike when writing to native FLAC, when writing to Ogg FLAC the - * write callback will be called twice when writing each audio - * frame; once for the page header, and once for the page body. - * When writing the page header, the \a samples argument to the - * write callback will be \c 0. - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param buffer An array of encoded data of length \a bytes. - * \param bytes The byte length of \a buffer. - * \param samples The number of samples encoded by \a buffer. - * \c 0 has a special meaning; see above. - * \param current_frame The number of the current frame being encoded. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - * \retval FLAC__StreamEncoderWriteStatus - * The callee's return status. - */ -typedef FLAC__StreamEncoderWriteStatus (*FLAC__StreamEncoderWriteCallback)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data); - -/** Signature for the seek callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_encoder_init*_stream(). The supplied function will be called - * when the encoder needs to seek the output stream. The encoder will pass - * the absolute byte offset to seek to, 0 meaning the beginning of the stream. - * - * Here is an example of a seek callback for stdio streams: - * \code - * FLAC__StreamEncoderSeekStatus seek_cb(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * if(file == stdin) - * return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED; - * else if(fseeko(file, (off_t)absolute_byte_offset, SEEK_SET) < 0) - * return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR; - * else - * return FLAC__STREAM_ENCODER_SEEK_STATUS_OK; - * } - * \endcode - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param absolute_byte_offset The offset from the beginning of the stream - * to seek to. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - * \retval FLAC__StreamEncoderSeekStatus - * The callee's return status. - */ -typedef FLAC__StreamEncoderSeekStatus (*FLAC__StreamEncoderSeekCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data); - -/** Signature for the tell callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_encoder_init*_stream(). The supplied function will be called - * when the encoder needs to know the current position of the output stream. - * - * \warning - * The callback must return the true current byte offset of the output to - * which the encoder is writing. If you are buffering the output, make - * sure and take this into account. If you are writing directly to a - * FILE* from your write callback, ftell() is sufficient. If you are - * writing directly to a file descriptor from your write callback, you - * can use lseek(fd, SEEK_CUR, 0). The encoder may later seek back to - * these points to rewrite metadata after encoding. - * - * Here is an example of a tell callback for stdio streams: - * \code - * FLAC__StreamEncoderTellStatus tell_cb(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * off_t pos; - * if(file == stdin) - * return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED; - * else if((pos = ftello(file)) < 0) - * return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR; - * else { - * *absolute_byte_offset = (FLAC__uint64)pos; - * return FLAC__STREAM_ENCODER_TELL_STATUS_OK; - * } - * } - * \endcode - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param absolute_byte_offset The address at which to store the current - * position of the output. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - * \retval FLAC__StreamEncoderTellStatus - * The callee's return status. - */ -typedef FLAC__StreamEncoderTellStatus (*FLAC__StreamEncoderTellCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data); - -/** Signature for the metadata callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_encoder_init*_stream(). The supplied function will be called - * once at the end of encoding with the populated STREAMINFO structure. This - * is so the client can seek back to the beginning of the file and write the - * STREAMINFO block with the correct statistics after encoding (like - * minimum/maximum frame size and total samples). - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param metadata The final populated STREAMINFO block. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - */ -typedef void (*FLAC__StreamEncoderMetadataCallback)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); - -/** Signature for the progress callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_encoder_init*_file() or FLAC__stream_encoder_init*_FILE(). - * The supplied function will be called when the encoder has finished - * writing a frame. The \c total_frames_estimate argument to the - * callback will be based on the value from - * FLAC__stream_encoder_set_total_samples_estimate(). - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param bytes_written Bytes written so far. - * \param samples_written Samples written so far. - * \param frames_written Frames written so far. - * \param total_frames_estimate The estimate of the total number of - * frames to be written. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - */ -typedef void (*FLAC__StreamEncoderProgressCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data); - - -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -/** Create a new stream encoder instance. The instance is created with - * default settings; see the individual FLAC__stream_encoder_set_*() - * functions for each setting's default. - * - * \retval FLAC__StreamEncoder* - * \c NULL if there was an error allocating memory, else the new instance. - */ -FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void); - -/** Free an encoder instance. Deletes the object pointed to by \a encoder. - * - * \param encoder A pointer to an existing encoder. - * \assert - * \code encoder != NULL \endcode - */ -FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder); - - -/*********************************************************************** - * - * Public class method prototypes - * - ***********************************************************************/ - -/** Set the serial number for the FLAC stream to use in the Ogg container. - * - * \note - * This does not need to be set for native FLAC encoding. - * - * \note - * It is recommended to set a serial number explicitly as the default of '0' - * may collide with other streams. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param serial_number See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_ogg_serial_number(FLAC__StreamEncoder *encoder, long serial_number); - -/** Set the "verify" flag. If \c true, the encoder will verify it's own - * encoded output by feeding it through an internal decoder and comparing - * the original signal against the decoded signal. If a mismatch occurs, - * the process call will return \c false. Note that this will slow the - * encoding process by the extra time required for decoding and comparison. - * - * \default \c false - * \param encoder An encoder instance to set. - * \param value Flag value (see above). - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value); - -/** Set the Subset flag. If \c true, - * the encoder will comply with the Subset and will check the - * settings during FLAC__stream_encoder_init_*() to see if all settings - * comply. If \c false, the settings may take advantage of the full - * range that the format allows. - * - * Make sure you know what it entails before setting this to \c false. - * - * \default \c true - * \param encoder An encoder instance to set. - * \param value Flag value (see above). - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value); - -/** Set the number of channels to be encoded. - * - * \default \c 2 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value); - -/** Set the sample resolution of the input to be encoded. - * - * \warning - * Do not feed the encoder data that is wider than the value you - * set here or you will generate an invalid stream. - * - * \default \c 16 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value); - -/** Set the sample rate (in Hz) of the input to be encoded. - * - * \default \c 44100 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value); - -/** Set the compression level - * - * The compression level is roughly proportional to the amount of effort - * the encoder expends to compress the file. A higher level usually - * means more computation but higher compression. The default level is - * suitable for most applications. - * - * Currently the levels range from \c 0 (fastest, least compression) to - * \c 8 (slowest, most compression). A value larger than \c 8 will be - * treated as \c 8. - * - * This function automatically calls the following other \c _set_ - * functions with appropriate values, so the client does not need to - * unless it specifically wants to override them: - * - FLAC__stream_encoder_set_do_mid_side_stereo() - * - FLAC__stream_encoder_set_loose_mid_side_stereo() - * - FLAC__stream_encoder_set_apodization() - * - FLAC__stream_encoder_set_max_lpc_order() - * - FLAC__stream_encoder_set_qlp_coeff_precision() - * - FLAC__stream_encoder_set_do_qlp_coeff_prec_search() - * - FLAC__stream_encoder_set_do_escape_coding() - * - FLAC__stream_encoder_set_do_exhaustive_model_search() - * - FLAC__stream_encoder_set_min_residual_partition_order() - * - FLAC__stream_encoder_set_max_residual_partition_order() - * - FLAC__stream_encoder_set_rice_parameter_search_dist() - * - * The actual values set for each level are: - * - * - * - * - * - * - * - * - * - * - * - * - *
level - * do mid-side stereo - * loose mid-side stereo - * apodization - * max lpc order - * qlp coeff precision - * qlp coeff prec search - * escape coding - * exhaustive model search - * min residual partition order - * max residual partition order - * rice parameter search dist - *
0 false false tukey(0.5) 0 0 false false false 0 3 0
1 true true tukey(0.5) 0 0 false false false 0 3 0
2 true false tukey(0.5) 0 0 false false false 0 3 0
3 false false tukey(0.5) 6 0 false false false 0 4 0
4 true true tukey(0.5) 8 0 false false false 0 4 0
5 true false tukey(0.5) 8 0 false false false 0 5 0
6 true false tukey(0.5) 8 0 false false false 0 6 0
7 true false tukey(0.5) 8 0 false false true 0 6 0
8 true false tukey(0.5) 12 0 false false true 0 6 0
- * - * \default \c 5 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, unsigned value); - -/** Set the blocksize to use while encoding. - * - * The number of samples to use per frame. Use \c 0 to let the encoder - * estimate a blocksize; this is usually best. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value); - -/** Set to \c true to enable mid-side encoding on stereo input. The - * number of channels must be 2 for this to have any effect. Set to - * \c false to use only independent channel coding. - * - * \default \c false - * \param encoder An encoder instance to set. - * \param value Flag value (see above). - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value); - -/** Set to \c true to enable adaptive switching between mid-side and - * left-right encoding on stereo input. Set to \c false to use - * exhaustive searching. Setting this to \c true requires - * FLAC__stream_encoder_set_do_mid_side_stereo() to also be set to - * \c true in order to have any effect. - * - * \default \c false - * \param encoder An encoder instance to set. - * \param value Flag value (see above). - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value); - -/** Sets the apodization function(s) the encoder will use when windowing - * audio data for LPC analysis. - * - * The \a specification is a plain ASCII string which specifies exactly - * which functions to use. There may be more than one (up to 32), - * separated by \c ';' characters. Some functions take one or more - * comma-separated arguments in parentheses. - * - * The available functions are \c bartlett, \c bartlett_hann, - * \c blackman, \c blackman_harris_4term_92db, \c connes, \c flattop, - * \c gauss(STDDEV), \c hamming, \c hann, \c kaiser_bessel, \c nuttall, - * \c rectangle, \c triangle, \c tukey(P), \c welch. - * - * For \c gauss(STDDEV), STDDEV specifies the standard deviation - * (0blocksize / (2 ^ order). - * - * Set both min and max values to \c 0 to force a single context, - * whose Rice parameter is based on the residual signal variance. - * Otherwise, set a min and max order, and the encoder will search - * all orders, using the mean of each context for its Rice parameter, - * and use the best. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value); - -/** Set the maximum partition order to search when coding the residual. - * This is used in tandem with - * FLAC__stream_encoder_set_min_residual_partition_order(). - * - * The partition order determines the context size in the residual. - * The context size will be approximately blocksize / (2 ^ order). - * - * Set both min and max values to \c 0 to force a single context, - * whose Rice parameter is based on the residual signal variance. - * Otherwise, set a min and max order, and the encoder will search - * all orders, using the mean of each context for its Rice parameter, - * and use the best. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value); - -/** Deprecated. Setting this value has no effect. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value); - -/** Set an estimate of the total samples that will be encoded. - * This is merely an estimate and may be set to \c 0 if unknown. - * This value will be written to the STREAMINFO block before encoding, - * and can remove the need for the caller to rewrite the value later - * if the value is known before encoding. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value); - -/** Set the metadata blocks to be emitted to the stream before encoding. - * A value of \c NULL, \c 0 implies no metadata; otherwise, supply an - * array of pointers to metadata blocks. The array is non-const since - * the encoder may need to change the \a is_last flag inside them, and - * in some cases update seek point offsets. Otherwise, the encoder will - * not modify or free the blocks. It is up to the caller to free the - * metadata blocks after encoding finishes. - * - * \note - * The encoder stores only copies of the pointers in the \a metadata array; - * the metadata blocks themselves must survive at least until after - * FLAC__stream_encoder_finish() returns. Do not free the blocks until then. - * - * \note - * The STREAMINFO block is always written and no STREAMINFO block may - * occur in the supplied array. - * - * \note - * By default the encoder does not create a SEEKTABLE. If one is supplied - * in the \a metadata array, but the client has specified that it does not - * support seeking, then the SEEKTABLE will be written verbatim. However - * by itself this is not very useful as the client will not know the stream - * offsets for the seekpoints ahead of time. In order to get a proper - * seektable the client must support seeking. See next note. - * - * \note - * SEEKTABLE blocks are handled specially. Since you will not know - * the values for the seek point stream offsets, you should pass in - * a SEEKTABLE 'template', that is, a SEEKTABLE object with the - * required sample numbers (or placeholder points), with \c 0 for the - * \a frame_samples and \a stream_offset fields for each point. If the - * client has specified that it supports seeking by providing a seek - * callback to FLAC__stream_encoder_init_stream() or both seek AND read - * callback to FLAC__stream_encoder_init_ogg_stream() (or by using - * FLAC__stream_encoder_init*_file() or FLAC__stream_encoder_init*_FILE()), - * then while it is encoding the encoder will fill the stream offsets in - * for you and when encoding is finished, it will seek back and write the - * real values into the SEEKTABLE block in the stream. There are helper - * routines for manipulating seektable template blocks; see metadata.h: - * FLAC__metadata_object_seektable_template_*(). If the client does - * not support seeking, the SEEKTABLE will have inaccurate offsets which - * will slow down or remove the ability to seek in the FLAC stream. - * - * \note - * The encoder instance \b will modify the first \c SEEKTABLE block - * as it transforms the template to a valid seektable while encoding, - * but it is still up to the caller to free all metadata blocks after - * encoding. - * - * \note - * A VORBIS_COMMENT block may be supplied. The vendor string in it - * will be ignored. libFLAC will use it's own vendor string. libFLAC - * will not modify the passed-in VORBIS_COMMENT's vendor string, it - * will simply write it's own into the stream. If no VORBIS_COMMENT - * block is present in the \a metadata array, libFLAC will write an - * empty one, containing only the vendor string. - * - * \note The Ogg FLAC mapping requires that the VORBIS_COMMENT block be - * the second metadata block of the stream. The encoder already supplies - * the STREAMINFO block automatically. If \a metadata does not contain a - * VORBIS_COMMENT block, the encoder will supply that too. Otherwise, if - * \a metadata does contain a VORBIS_COMMENT block and it is not the - * first, the init function will reorder \a metadata by moving the - * VORBIS_COMMENT block to the front; the relative ordering of the other - * blocks will remain as they were. - * - * \note The Ogg FLAC mapping limits the number of metadata blocks per - * stream to \c 65535. If \a num_blocks exceeds this the function will - * return \c false. - * - * \default \c NULL, 0 - * \param encoder An encoder instance to set. - * \param metadata See above. - * \param num_blocks See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - * \c false if the encoder is already initialized, or if - * \a num_blocks > 65535 if encoding to Ogg FLAC, else \c true. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks); - -/** Get the current encoder state. - * - * \param encoder An encoder instance to query. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__StreamEncoderState - * The current encoder state. - */ -FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder); - -/** Get the state of the verify stream decoder. - * Useful when the stream encoder state is - * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. - * - * \param encoder An encoder instance to query. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__StreamDecoderState - * The verify stream decoder state. - */ -FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder); - -/** Get the current encoder state as a C string. - * This version automatically resolves - * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR by getting the - * verify decoder's state. - * - * \param encoder A encoder instance to query. - * \assert - * \code encoder != NULL \endcode - * \retval const char * - * The encoder state as a C string. Do not modify the contents. - */ -FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__StreamEncoder *encoder); - -/** Get relevant values about the nature of a verify decoder error. - * Useful when the stream encoder state is - * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. The arguments should - * be addresses in which the stats will be returned, or NULL if value - * is not desired. - * - * \param encoder An encoder instance to query. - * \param absolute_sample The absolute sample number of the mismatch. - * \param frame_number The number of the frame in which the mismatch occurred. - * \param channel The channel in which the mismatch occurred. - * \param sample The number of the sample (relative to the frame) in - * which the mismatch occurred. - * \param expected The expected value for the sample in question. - * \param got The actual value returned by the decoder. - * \assert - * \code encoder != NULL \endcode - */ -FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got); - -/** Get the "verify" flag. - * - * \param encoder An encoder instance to query. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * See FLAC__stream_encoder_set_verify(). - */ -FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder); - -/** Get the frame header. - * - * \param encoder An initialized encoder instance in the OK state. - * \param buffer An array of pointers to each channel's signal. - * \param samples The number of samples in one channel. - * \assert - * \code encoder != NULL \endcode - * \code FLAC__stream_encoder_get_state(encoder) == FLAC__STREAM_ENCODER_OK \endcode - * \retval FLAC__bool - * \c true if successful, else \c false; in this case, check the - * encoder state with FLAC__stream_encoder_get_state() to see what - * went wrong. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples); - -/** Submit data for encoding. - * This version allows you to supply the input data where the channels - * are interleaved into a single array (i.e. channel0_sample0, - * channel1_sample0, ... , channelN_sample0, channel0_sample1, ...). - * The samples need not be block-aligned but they must be - * sample-aligned, i.e. the first value should be channel0_sample0 - * and the last value channelN_sampleM. Each sample should be a signed - * integer, right-justified to the resolution set by - * FLAC__stream_encoder_set_bits_per_sample(). For example, if the - * resolution is 16 bits per sample, the samples should all be in the - * range [-32768,32767]. - * - * For applications where channel order is important, channels must - * follow the order as described in the - * frame header. - * - * \param encoder An initialized encoder instance in the OK state. - * \param buffer An array of channel-interleaved data (see above). - * \param samples The number of samples in one channel, the same as for - * FLAC__stream_encoder_process(). For example, if - * encoding two channels, \c 1000 \a samples corresponds - * to a \a buffer of 2000 values. - * \assert - * \code encoder != NULL \endcode - * \code FLAC__stream_encoder_get_state(encoder) == FLAC__STREAM_ENCODER_OK \endcode - * \retval FLAC__bool - * \c true if successful, else \c false; in this case, check the - * encoder state with FLAC__stream_encoder_get_state() to see what - * went wrong. - */ -FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples); - -/* \} */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/Windows/include/ogg/config_types.h b/platform/Windows/include/ogg/config_types.h deleted file mode 100644 index 4b00047a0..000000000 --- a/platform/Windows/include/ogg/config_types.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __CONFIG_TYPES_H__ -#define __CONFIG_TYPES_H__ - -/* these are filled in by configure */ -#define INCLUDE_INTTYPES_H 1 -#define INCLUDE_STDINT_H 1 -#define INCLUDE_SYS_TYPES_H 1 - -#if INCLUDE_INTTYPES_H -# include -#endif -#if INCLUDE_STDINT_H -# include -#endif -#if INCLUDE_SYS_TYPES_H -# include -#endif - -typedef int16_t ogg_int16_t; -typedef uint16_t ogg_uint16_t; -typedef int32_t ogg_int32_t; -typedef uint32_t ogg_uint32_t; -typedef int64_t ogg_int64_t; - -#endif diff --git a/platform/Windows/include/ogg/ogg.h b/platform/Windows/include/ogg/ogg.h deleted file mode 100644 index cea4ebed7..000000000 --- a/platform/Windows/include/ogg/ogg.h +++ /dev/null @@ -1,210 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: toplevel libogg include - last mod: $Id: ogg.h 18044 2011-08-01 17:55:20Z gmaxwell $ - - ********************************************************************/ -#ifndef _OGG_H -#define _OGG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef struct { - void *iov_base; - size_t iov_len; -} ogg_iovec_t; - -typedef struct { - long endbyte; - int endbit; - - unsigned char *buffer; - unsigned char *ptr; - long storage; -} oggpack_buffer; - -/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/ - -typedef struct { - unsigned char *header; - long header_len; - unsigned char *body; - long body_len; -} ogg_page; - -/* ogg_stream_state contains the current encode/decode state of a logical - Ogg bitstream **********************************************************/ - -typedef struct { - unsigned char *body_data; /* bytes from packet bodies */ - long body_storage; /* storage elements allocated */ - long body_fill; /* elements stored; fill mark */ - long body_returned; /* elements of fill returned */ - - - int *lacing_vals; /* The values that will go to the segment table */ - ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact - this way, but it is simple coupled to the - lacing fifo */ - long lacing_storage; - long lacing_fill; - long lacing_packet; - long lacing_returned; - - unsigned char header[282]; /* working space for header encode */ - int header_fill; - - int e_o_s; /* set when we have buffered the last packet in the - logical bitstream */ - int b_o_s; /* set after we've written the initial page - of a logical bitstream */ - long serialno; - long pageno; - ogg_int64_t packetno; /* sequence number for decode; the framing - knows where there's a hole in the data, - but we need coupling so that the codec - (which is in a separate abstraction - layer) also knows about the gap */ - ogg_int64_t granulepos; - -} ogg_stream_state; - -/* ogg_packet is used to encapsulate the data and metadata belonging - to a single raw Ogg/Vorbis packet *************************************/ - -typedef struct { - unsigned char *packet; - long bytes; - long b_o_s; - long e_o_s; - - ogg_int64_t granulepos; - - ogg_int64_t packetno; /* sequence number for decode; the framing - knows where there's a hole in the data, - but we need coupling so that the codec - (which is in a separate abstraction - layer) also knows about the gap */ -} ogg_packet; - -typedef struct { - unsigned char *data; - int storage; - int fill; - int returned; - - int unsynced; - int headerbytes; - int bodybytes; -} ogg_sync_state; - -/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ - -extern void oggpack_writeinit(oggpack_buffer *b); -extern int oggpack_writecheck(oggpack_buffer *b); -extern void oggpack_writetrunc(oggpack_buffer *b,long bits); -extern void oggpack_writealign(oggpack_buffer *b); -extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits); -extern void oggpack_reset(oggpack_buffer *b); -extern void oggpack_writeclear(oggpack_buffer *b); -extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); -extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); -extern long oggpack_look(oggpack_buffer *b,int bits); -extern long oggpack_look1(oggpack_buffer *b); -extern void oggpack_adv(oggpack_buffer *b,int bits); -extern void oggpack_adv1(oggpack_buffer *b); -extern long oggpack_read(oggpack_buffer *b,int bits); -extern long oggpack_read1(oggpack_buffer *b); -extern long oggpack_bytes(oggpack_buffer *b); -extern long oggpack_bits(oggpack_buffer *b); -extern unsigned char *oggpack_get_buffer(oggpack_buffer *b); - -extern void oggpackB_writeinit(oggpack_buffer *b); -extern int oggpackB_writecheck(oggpack_buffer *b); -extern void oggpackB_writetrunc(oggpack_buffer *b,long bits); -extern void oggpackB_writealign(oggpack_buffer *b); -extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits); -extern void oggpackB_reset(oggpack_buffer *b); -extern void oggpackB_writeclear(oggpack_buffer *b); -extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); -extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits); -extern long oggpackB_look(oggpack_buffer *b,int bits); -extern long oggpackB_look1(oggpack_buffer *b); -extern void oggpackB_adv(oggpack_buffer *b,int bits); -extern void oggpackB_adv1(oggpack_buffer *b); -extern long oggpackB_read(oggpack_buffer *b,int bits); -extern long oggpackB_read1(oggpack_buffer *b); -extern long oggpackB_bytes(oggpack_buffer *b); -extern long oggpackB_bits(oggpack_buffer *b); -extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b); - -/* Ogg BITSTREAM PRIMITIVES: encoding **************************/ - -extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); -extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, - int count, long e_o_s, ogg_int64_t granulepos); -extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); -extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill); -extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); -extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill); - -/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ - -extern int ogg_sync_init(ogg_sync_state *oy); -extern int ogg_sync_clear(ogg_sync_state *oy); -extern int ogg_sync_reset(ogg_sync_state *oy); -extern int ogg_sync_destroy(ogg_sync_state *oy); -extern int ogg_sync_check(ogg_sync_state *oy); - -extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); -extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); -extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); -extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); -extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); -extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); -extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); - -/* Ogg BITSTREAM PRIMITIVES: general ***************************/ - -extern int ogg_stream_init(ogg_stream_state *os,int serialno); -extern int ogg_stream_clear(ogg_stream_state *os); -extern int ogg_stream_reset(ogg_stream_state *os); -extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); -extern int ogg_stream_destroy(ogg_stream_state *os); -extern int ogg_stream_check(ogg_stream_state *os); -extern int ogg_stream_eos(ogg_stream_state *os); - -extern void ogg_page_checksum_set(ogg_page *og); - -extern int ogg_page_version(const ogg_page *og); -extern int ogg_page_continued(const ogg_page *og); -extern int ogg_page_bos(const ogg_page *og); -extern int ogg_page_eos(const ogg_page *og); -extern ogg_int64_t ogg_page_granulepos(const ogg_page *og); -extern int ogg_page_serialno(const ogg_page *og); -extern long ogg_page_pageno(const ogg_page *og); -extern int ogg_page_packets(const ogg_page *og); - -extern void ogg_packet_clear(ogg_packet *op); - - -#ifdef __cplusplus -} -#endif - -#endif /* _OGG_H */ diff --git a/platform/Windows/include/ogg/os_types.h b/platform/Windows/include/ogg/os_types.h deleted file mode 100644 index 8bf82107e..000000000 --- a/platform/Windows/include/ogg/os_types.h +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: #ifdef jail to whip a few platforms into the UNIX ideal. - last mod: $Id: os_types.h 19098 2014-02-26 19:06:45Z giles $ - - ********************************************************************/ -#ifndef _OS_TYPES_H -#define _OS_TYPES_H - -/* make it easy on the folks that want to compile the libs with a - different malloc than stdlib */ -#define _ogg_malloc malloc -#define _ogg_calloc calloc -#define _ogg_realloc realloc -#define _ogg_free free - -#if defined(_WIN32) - -# if defined(__CYGWIN__) -# include - typedef int16_t ogg_int16_t; - typedef uint16_t ogg_uint16_t; - typedef int32_t ogg_int32_t; - typedef uint32_t ogg_uint32_t; - typedef int64_t ogg_int64_t; - typedef uint64_t ogg_uint64_t; -# elif defined(__MINGW32__) -# include - typedef short ogg_int16_t; - typedef unsigned short ogg_uint16_t; - typedef int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef long long ogg_int64_t; - typedef unsigned long long ogg_uint64_t; -# elif defined(__MWERKS__) - typedef long long ogg_int64_t; - typedef int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef short ogg_int16_t; - typedef unsigned short ogg_uint16_t; -# else - /* MSVC/Borland */ - typedef __int64 ogg_int64_t; - typedef __int32 ogg_int32_t; - typedef unsigned __int32 ogg_uint32_t; - typedef __int16 ogg_int16_t; - typedef unsigned __int16 ogg_uint16_t; -# endif - -#elif defined(__MACOS__) - -# include - typedef SInt16 ogg_int16_t; - typedef UInt16 ogg_uint16_t; - typedef SInt32 ogg_int32_t; - typedef UInt32 ogg_uint32_t; - typedef SInt64 ogg_int64_t; - -#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ - -# include - typedef int16_t ogg_int16_t; - typedef uint16_t ogg_uint16_t; - typedef int32_t ogg_int32_t; - typedef uint32_t ogg_uint32_t; - typedef int64_t ogg_int64_t; - -#elif defined(__HAIKU__) - - /* Haiku */ -# include - typedef short ogg_int16_t; - typedef unsigned short ogg_uint16_t; - typedef int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef long long ogg_int64_t; - -#elif defined(__BEOS__) - - /* Be */ -# include - typedef int16_t ogg_int16_t; - typedef uint16_t ogg_uint16_t; - typedef int32_t ogg_int32_t; - typedef uint32_t ogg_uint32_t; - typedef int64_t ogg_int64_t; - -#elif defined (__EMX__) - - /* OS/2 GCC */ - typedef short ogg_int16_t; - typedef unsigned short ogg_uint16_t; - typedef int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef long long ogg_int64_t; - -#elif defined (DJGPP) - - /* DJGPP */ - typedef short ogg_int16_t; - typedef int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef long long ogg_int64_t; - -#elif defined(R5900) - - /* PS2 EE */ - typedef long ogg_int64_t; - typedef int ogg_int32_t; - typedef unsigned ogg_uint32_t; - typedef short ogg_int16_t; - -#elif defined(__SYMBIAN32__) - - /* Symbian GCC */ - typedef signed short ogg_int16_t; - typedef unsigned short ogg_uint16_t; - typedef signed int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef long long int ogg_int64_t; - -#elif defined(__TMS320C6X__) - - /* TI C64x compiler */ - typedef signed short ogg_int16_t; - typedef unsigned short ogg_uint16_t; - typedef signed int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef long long int ogg_int64_t; - -#else - -# include - -#endif - -#endif /* _OS_TYPES_H */ diff --git a/platform/Windows/include/vorbis/codec.h b/platform/Windows/include/vorbis/codec.h deleted file mode 100644 index 999aa3351..000000000 --- a/platform/Windows/include/vorbis/codec.h +++ /dev/null @@ -1,243 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - - ******************************************************************** - - function: libvorbis codec headers - last mod: $Id: codec.h 17021 2010-03-24 09:29:41Z xiphmont $ - - ********************************************************************/ - -#ifndef _vorbis_codec_h_ -#define _vorbis_codec_h_ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -#include - -typedef struct vorbis_info{ - int version; - int channels; - long rate; - - /* The below bitrate declarations are *hints*. - Combinations of the three values carry the following implications: - - all three set to the same value: - implies a fixed rate bitstream - only nominal set: - implies a VBR stream that averages the nominal bitrate. No hard - upper/lower limit - upper and or lower set: - implies a VBR bitstream that obeys the bitrate limits. nominal - may also be set to give a nominal rate. - none set: - the coder does not care to speculate. - */ - - long bitrate_upper; - long bitrate_nominal; - long bitrate_lower; - long bitrate_window; - - void *codec_setup; -} vorbis_info; - -/* vorbis_dsp_state buffers the current vorbis audio - analysis/synthesis state. The DSP state belongs to a specific - logical bitstream ****************************************************/ -typedef struct vorbis_dsp_state{ - int analysisp; - vorbis_info *vi; - - float **pcm; - float **pcmret; - int pcm_storage; - int pcm_current; - int pcm_returned; - - int preextrapolate; - int eofflag; - - long lW; - long W; - long nW; - long centerW; - - ogg_int64_t granulepos; - ogg_int64_t sequence; - - ogg_int64_t glue_bits; - ogg_int64_t time_bits; - ogg_int64_t floor_bits; - ogg_int64_t res_bits; - - void *backend_state; -} vorbis_dsp_state; - -typedef struct vorbis_block{ - /* necessary stream state for linking to the framing abstraction */ - float **pcm; /* this is a pointer into local storage */ - oggpack_buffer opb; - - long lW; - long W; - long nW; - int pcmend; - int mode; - - int eofflag; - ogg_int64_t granulepos; - ogg_int64_t sequence; - vorbis_dsp_state *vd; /* For read-only access of configuration */ - - /* local storage to avoid remallocing; it's up to the mapping to - structure it */ - void *localstore; - long localtop; - long localalloc; - long totaluse; - struct alloc_chain *reap; - - /* bitmetrics for the frame */ - long glue_bits; - long time_bits; - long floor_bits; - long res_bits; - - void *internal; - -} vorbis_block; - -/* vorbis_block is a single block of data to be processed as part of -the analysis/synthesis stream; it belongs to a specific logical -bitstream, but is independent from other vorbis_blocks belonging to -that logical bitstream. *************************************************/ - -struct alloc_chain{ - void *ptr; - struct alloc_chain *next; -}; - -/* vorbis_info contains all the setup information specific to the - specific compression/decompression mode in progress (eg, - psychoacoustic settings, channel setup, options, codebook - etc). vorbis_info and substructures are in backends.h. -*********************************************************************/ - -/* the comments are not part of vorbis_info so that vorbis_info can be - static storage */ -typedef struct vorbis_comment{ - /* unlimited user comment fields. libvorbis writes 'libvorbis' - whatever vendor is set to in encode */ - char **user_comments; - int *comment_lengths; - int comments; - char *vendor; - -} vorbis_comment; - - -/* libvorbis encodes in two abstraction layers; first we perform DSP - and produce a packet (see docs/analysis.txt). The packet is then - coded into a framed OggSquish bitstream by the second layer (see - docs/framing.txt). Decode is the reverse process; we sync/frame - the bitstream and extract individual packets, then decode the - packet back into PCM audio. - - The extra framing/packetizing is used in streaming formats, such as - files. Over the net (such as with UDP), the framing and - packetization aren't necessary as they're provided by the transport - and the streaming layer is not used */ - -/* Vorbis PRIMITIVES: general ***************************************/ - -extern void vorbis_info_init(vorbis_info *vi); -extern void vorbis_info_clear(vorbis_info *vi); -extern int vorbis_info_blocksize(vorbis_info *vi,int zo); -extern void vorbis_comment_init(vorbis_comment *vc); -extern void vorbis_comment_add(vorbis_comment *vc, const char *comment); -extern void vorbis_comment_add_tag(vorbis_comment *vc, - const char *tag, const char *contents); -extern char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count); -extern int vorbis_comment_query_count(vorbis_comment *vc, const char *tag); -extern void vorbis_comment_clear(vorbis_comment *vc); - -extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); -extern int vorbis_block_clear(vorbis_block *vb); -extern void vorbis_dsp_clear(vorbis_dsp_state *v); -extern double vorbis_granule_time(vorbis_dsp_state *v, - ogg_int64_t granulepos); - -extern const char *vorbis_version_string(void); - -/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/ - -extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); -extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op); -extern int vorbis_analysis_headerout(vorbis_dsp_state *v, - vorbis_comment *vc, - ogg_packet *op, - ogg_packet *op_comm, - ogg_packet *op_code); -extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals); -extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); -extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); -extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); - -extern int vorbis_bitrate_addblock(vorbis_block *vb); -extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, - ogg_packet *op); - -/* Vorbis PRIMITIVES: synthesis layer *******************************/ -extern int vorbis_synthesis_idheader(ogg_packet *op); -extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, - ogg_packet *op); - -extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); -extern int vorbis_synthesis_restart(vorbis_dsp_state *v); -extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); -extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); -extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); -extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm); -extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm); -extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); -extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); - -extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag); -extern int vorbis_synthesis_halfrate_p(vorbis_info *v); - -/* Vorbis ERRORS and return codes ***********************************/ - -#define OV_FALSE -1 -#define OV_EOF -2 -#define OV_HOLE -3 - -#define OV_EREAD -128 -#define OV_EFAULT -129 -#define OV_EIMPL -130 -#define OV_EINVAL -131 -#define OV_ENOTVORBIS -132 -#define OV_EBADHEADER -133 -#define OV_EVERSION -134 -#define OV_ENOTAUDIO -135 -#define OV_EBADPACKET -136 -#define OV_EBADLINK -137 -#define OV_ENOSEEK -138 - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif - diff --git a/platform/Windows/include/vorbis/vorbisfile.h b/platform/Windows/include/vorbis/vorbisfile.h deleted file mode 100644 index 9271331e7..000000000 --- a/platform/Windows/include/vorbis/vorbisfile.h +++ /dev/null @@ -1,206 +0,0 @@ -/******************************************************************** - * * - * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * - * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * - * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * - * * - * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * - * by the Xiph.Org Foundation http://www.xiph.org/ * - * * - ******************************************************************** - - function: stdio-based convenience library for opening/seeking/decoding - last mod: $Id: vorbisfile.h 17182 2010-04-29 03:48:32Z xiphmont $ - - ********************************************************************/ - -#ifndef _OV_FILE_H_ -#define _OV_FILE_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -#include -#include "codec.h" - -/* The function prototypes for the callbacks are basically the same as for - * the stdio functions fread, fseek, fclose, ftell. - * The one difference is that the FILE * arguments have been replaced with - * a void * - this is to be used as a pointer to whatever internal data these - * functions might need. In the stdio case, it's just a FILE * cast to a void * - * - * If you use other functions, check the docs for these functions and return - * the right values. For seek_func(), you *MUST* return -1 if the stream is - * unseekable - */ -typedef struct { - size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); - int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); - int (*close_func) (void *datasource); - long (*tell_func) (void *datasource); -} ov_callbacks; - -#ifndef OV_EXCLUDE_STATIC_CALLBACKS - -/* a few sets of convenient callbacks, especially for use under - * Windows where ov_open_callbacks() should always be used instead of - * ov_open() to avoid problems with incompatible crt.o version linking - * issues. */ - -static int _ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){ - if(f==NULL)return(-1); - -#ifdef __MINGW32__ - return fseeko64(f,off,whence); -#elif defined (_WIN32) - return _fseeki64(f,off,whence); -#else - return fseek(f,off,whence); -#endif -} - -/* These structs below (OV_CALLBACKS_DEFAULT etc) are defined here as - * static data. That means that every file which includes this header - * will get its own copy of these structs whether it uses them or - * not unless it #defines OV_EXCLUDE_STATIC_CALLBACKS. - * These static symbols are essential on platforms such as Windows on - * which several different versions of stdio support may be linked to - * by different DLLs, and we need to be certain we know which one - * we're using (the same one as the main application). - */ - -static ov_callbacks OV_CALLBACKS_DEFAULT = { - (size_t (*)(void *, size_t, size_t, void *)) fread, - (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, - (int (*)(void *)) fclose, - (long (*)(void *)) ftell -}; - -static ov_callbacks OV_CALLBACKS_NOCLOSE = { - (size_t (*)(void *, size_t, size_t, void *)) fread, - (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, - (int (*)(void *)) NULL, - (long (*)(void *)) ftell -}; - -static ov_callbacks OV_CALLBACKS_STREAMONLY = { - (size_t (*)(void *, size_t, size_t, void *)) fread, - (int (*)(void *, ogg_int64_t, int)) NULL, - (int (*)(void *)) fclose, - (long (*)(void *)) NULL -}; - -static ov_callbacks OV_CALLBACKS_STREAMONLY_NOCLOSE = { - (size_t (*)(void *, size_t, size_t, void *)) fread, - (int (*)(void *, ogg_int64_t, int)) NULL, - (int (*)(void *)) NULL, - (long (*)(void *)) NULL -}; - -#endif - -#define NOTOPEN 0 -#define PARTOPEN 1 -#define OPENED 2 -#define STREAMSET 3 -#define INITSET 4 - -typedef struct OggVorbis_File { - void *datasource; /* Pointer to a FILE *, etc. */ - int seekable; - ogg_int64_t offset; - ogg_int64_t end; - ogg_sync_state oy; - - /* If the FILE handle isn't seekable (eg, a pipe), only the current - stream appears */ - int links; - ogg_int64_t *offsets; - ogg_int64_t *dataoffsets; - long *serialnos; - ogg_int64_t *pcmlengths; /* overloaded to maintain binary - compatibility; x2 size, stores both - beginning and end values */ - vorbis_info *vi; - vorbis_comment *vc; - - /* Decoding working state local storage */ - ogg_int64_t pcm_offset; - int ready_state; - long current_serialno; - int current_link; - - double bittrack; - double samptrack; - - ogg_stream_state os; /* take physical pages, weld into a logical - stream of packets */ - vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ - vorbis_block vb; /* local working space for packet->PCM decode */ - - ov_callbacks callbacks; - -} OggVorbis_File; - - -extern int ov_clear(OggVorbis_File *vf); -extern int ov_fopen(const char *path,OggVorbis_File *vf); -extern int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); -extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, - const char *initial, long ibytes, ov_callbacks callbacks); - -extern int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); -extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, - const char *initial, long ibytes, ov_callbacks callbacks); -extern int ov_test_open(OggVorbis_File *vf); - -extern long ov_bitrate(OggVorbis_File *vf,int i); -extern long ov_bitrate_instant(OggVorbis_File *vf); -extern long ov_streams(OggVorbis_File *vf); -extern long ov_seekable(OggVorbis_File *vf); -extern long ov_serialnumber(OggVorbis_File *vf,int i); - -extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i); -extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i); -extern double ov_time_total(OggVorbis_File *vf,int i); - -extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_time_seek(OggVorbis_File *vf,double pos); -extern int ov_time_seek_page(OggVorbis_File *vf,double pos); - -extern int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos); -extern int ov_time_seek_lap(OggVorbis_File *vf,double pos); -extern int ov_time_seek_page_lap(OggVorbis_File *vf,double pos); - -extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf); -extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf); -extern double ov_time_tell(OggVorbis_File *vf); - -extern vorbis_info *ov_info(OggVorbis_File *vf,int link); -extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link); - -extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples, - int *bitstream); -extern long ov_read_filter(OggVorbis_File *vf,char *buffer,int length, - int bigendianp,int word,int sgned,int *bitstream, - void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param); -extern long ov_read(OggVorbis_File *vf,char *buffer,int length, - int bigendianp,int word,int sgned,int *bitstream); -extern int ov_crosslap(OggVorbis_File *vf1,OggVorbis_File *vf2); - -extern int ov_halfrate(OggVorbis_File *vf,int flag); -extern int ov_halfrate_p(OggVorbis_File *vf); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif - diff --git a/platform/Windows/lib/32/libogg.lib b/platform/Windows/lib/32/libogg.lib deleted file mode 100644 index efd959cbe..000000000 Binary files a/platform/Windows/lib/32/libogg.lib and /dev/null differ diff --git a/platform/Windows/lib/32/libvorbis.lib b/platform/Windows/lib/32/libvorbis.lib deleted file mode 100644 index ccf4c002d..000000000 Binary files a/platform/Windows/lib/32/libvorbis.lib and /dev/null differ diff --git a/platform/Windows/lib/32/libvorbisfile.lib b/platform/Windows/lib/32/libvorbisfile.lib deleted file mode 100644 index 7fe2e0c13..000000000 Binary files a/platform/Windows/lib/32/libvorbisfile.lib and /dev/null differ diff --git a/platform/Windows/lib/64/libogg.lib b/platform/Windows/lib/64/libogg.lib deleted file mode 100644 index d6cad22a4..000000000 Binary files a/platform/Windows/lib/64/libogg.lib and /dev/null differ diff --git a/platform/Windows/lib/64/libvorbis.lib b/platform/Windows/lib/64/libvorbis.lib deleted file mode 100644 index e25f02831..000000000 Binary files a/platform/Windows/lib/64/libvorbis.lib and /dev/null differ diff --git a/platform/Windows/lib/64/libvorbisfile.lib b/platform/Windows/lib/64/libvorbisfile.lib deleted file mode 100644 index 6ddacdfad..000000000 Binary files a/platform/Windows/lib/64/libvorbisfile.lib and /dev/null differ diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index e52c18102..396d84942 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -104,10 +104,7 @@ if( WIN32 ) libSDL2main libSDL2 - # this local library crap needs to go away. The Ogg/Vorbis libraries are easy to replace with libsndfile but there doesn't seem to be anything to get a working libvpx that doesn't force linking with MinGW dependencies. - libogg - libvorbis - libvorbisfile + # this local library crap needs to go away. Sadly there doesn't seem to be anything to get a working libvpx that doesn't force linking with MinGW dependencies. libvpx libcompat-to-msvc @@ -476,7 +473,6 @@ endif() # Start defining source files for Demolition set( PLAT_WIN32_SOURCES - audiolib/src/driver_directsound.cpp glad/src/glad_wgl.c platform/win32/winbits.cpp platform/win32/i_specialpaths.cpp @@ -489,8 +485,6 @@ set( PLAT_WIN32_SOURCES ) set( PLAT_POSIX_SOURCES - #audiolib/src/driver_sdl.cpp - #audiolib/src/sdlmusic.cpp #platform/gtk/startgtk.game.cpp ) @@ -605,8 +599,6 @@ add_definitions(-DOPNMIDI_DISABLE_GX_EMULATOR) # Project files should be aware of the header files. We can GLOB these since # there's generally a new cpp for every header so this file will get changed file( GLOB HEADER_FILES - audiolib/include/*.h - audiolib/src/*.h build/include/*.h glad/include/glad/*.h glad/include/Khr/*.h @@ -614,8 +606,6 @@ file( GLOB HEADER_FILES libsmackerdec/include/*.h libxmp-lite/include/libxmp-lite/*.h libxmp-lite/src/*.h - mact/include/*.h - mact/src/*.h common/*.h common/2d/*.h common/fonts/*.h @@ -623,7 +613,10 @@ file( GLOB HEADER_FILES common/console/*.h common/filesystem/*.h common/music/*.h + common/sound/*.h + common/sound/backend/*.h common/menu/*.h + common/input/*.h build/src/*.h thirdparty/include/*.h @@ -638,7 +631,6 @@ file( GLOB HEADER_FILES # without being compiled. set( NOT_COMPILED_SOURCE_FILES ${OTHER_SYSTEM_SOURCES} - build/src/sdlkeytrans.cpp sc_man_scanner.h common/utility/sc_man_scanner.re ) @@ -666,22 +658,6 @@ set( FASTMATH_SOURCES set (PCH_SOURCES - audiolib/src/drivers.cpp - audiolib/src/driver_adlib.cpp - audiolib/src/driver_sdl.cpp - audiolib/src/driver_winmm.cpp - audiolib/src/formats.cpp - audiolib/src/fx_man.cpp - audiolib/src/gmtimbre.cpp - audiolib/src/midi.cpp - audiolib/src/mix.cpp - audiolib/src/mixst.cpp - audiolib/src/multivoc.cpp - audiolib/src/music.cpp - audiolib/src/opl3.cpp - audiolib/src/pitch.cpp - audiolib/src/vorbis.cpp - glbackend/gl_hwtexture.cpp glbackend/gl_samplers.cpp glbackend/gl_shader.cpp @@ -691,11 +667,6 @@ set (PCH_SOURCES glbackend/gl_buffers.cpp glbackend/hw_draw2d.cpp - mact/src/animlib.cpp - mact/src/control.cpp - mact/src/joystick.cpp - mact/src/input.cpp - thirdparty/src/base64.cpp thirdparty/src/sjson.cpp thirdparty/src/fix16.cpp @@ -714,7 +685,6 @@ set (PCH_SOURCES build/src/a-c.cpp build/src/animvpx.cpp build/src/baselayer.cpp - build/src/cache1d.cpp build/src/clip.cpp build/src/colmatch.cpp build/src/common.cpp @@ -729,7 +699,6 @@ set (PCH_SOURCES build/src/palette.cpp build/src/polymost.cpp build/src/pragmas.cpp - build/src/screenshot.cpp build/src/scriptfile.cpp build/src/sdlayer.cpp build/src/smalltextfont.cpp @@ -739,6 +708,7 @@ set (PCH_SOURCES build/src/timer.cpp build/src/voxmodel.cpp + common/animlib.cpp common/rts.cpp common/gameconfigfile.cpp common/gamecvars.cpp @@ -752,6 +722,7 @@ set (PCH_SOURCES common/compositesavegame.cpp common/savegamehelp.cpp common/quotes.cpp + common/screenshot.cpp common/2d/v_2ddrawer.cpp common/2d/v_draw.cpp @@ -824,9 +795,12 @@ set (PCH_SOURCES common/music/music_config.cpp common/music/music_midi_base.cpp common/music/s_advsound.cpp - common/music/backend/oalsound.cpp - common/music/backend/i_sound.cpp - + + common/sound/backend/oalsound.cpp + common/sound/backend/i_sound.cpp + common/sound/s_sound.cpp + common/sound/s_environment.cpp + common/menu/imagescroller.cpp common/menu/joystickmenu.cpp common/menu/listmenu.cpp @@ -837,6 +811,12 @@ set (PCH_SOURCES common/menu/menuinput.cpp common/menu/messagebox.cpp common/menu/optionmenu.cpp + + common/input/i_gui.cpp + common/input/i_joystick.cpp + common/input/i_input.cpp + common/input/m_joy.cpp + common/input/input.cpp ) if( MSVC ) @@ -883,8 +863,6 @@ target_link_libraries( demolition ${DEMOLITION_LIBS} gdtoa lzma duke3d blood rr include_directories( ${CMAKE_CURRENT_SOURCE_DIR} build/include - mact/include - audiolib/include glad/include libxmp-lite/include libxmp-lite/include/libxmp-lite @@ -899,8 +877,11 @@ include_directories( common/textures common/filesystem common/music + common/sound + common/sound/backend common/dobject common/menu + common/input platform ${CMAKE_BINARY_DIR}/libraries/gdtoa @@ -1009,11 +990,10 @@ source_group("Code\\Console" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/co source_group("Code\\Fonts" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/fonts/.+") source_group("Code\\File System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/.+") source_group("Code\\Music" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/music/.+") +source_group("Code\\Sound" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/sound/.+") +source_group("Code\\Sound\\Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/sound/backend/.+") source_group("Code\\DObject" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/dobject/.+") source_group("Code\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/menu/.+") -source_group("Utility\\Audiolib" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/.+") -source_group("Utility\\Audiolib Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/include/.+") -source_group("Utility\\Audiolib Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/audiolib/src/.+") source_group("Utility\\Glad" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/glad/.+") source_group("Utility\\Glad Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/glad/include/glad/.+") source_group("Utility\\Glad Khr Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/glad/include/Khr/.+") @@ -1024,9 +1004,6 @@ source_group("Utility\\Smackerdec\\Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT source_group("Utility\\XMP-Lite" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libxmp-lite/.+") source_group("Utility\\XMP-Lite Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libxmp-lite/include/libxmp-lite/.+") source_group("Utility\\XMP-Lite Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libxmp-lite/src/.+") -source_group("Utility\\Mact" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/mact/.+") -source_group("Utility\\Mact Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/mact/include/.+") -source_group("Utility\\Mact Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/mact/src/.+") source_group("Utility\\Third Party" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/.+") source_group("Utility\\Third Party Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/include/.+") source_group("Utility\\Third Party Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/src/.+") diff --git a/source/audiolib/gpl-2.0.txt b/source/audiolib/gpl-2.0.txt deleted file mode 100644 index d159169d1..000000000 --- a/source/audiolib/gpl-2.0.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/source/audiolib/include/al_midi.h b/source/audiolib/include/al_midi.h deleted file mode 100644 index 1dbb1608a..000000000 --- a/source/audiolib/include/al_midi.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef __AL_MIDI_H -#define __AL_MIDI_H - -#include "opl3.h" - -#include - -typedef struct -{ - uint8_t SAVEK[2]; - uint8_t Level[2]; - uint8_t Env1[2]; - uint8_t Env2[2]; - uint8_t Wave[2]; - uint8_t Feedback; - int8_t Transpose; - int8_t Velocity; -} AdLibTimbre; - -extern AdLibTimbre ADLIB_TimbreBank[256]; - -opl3_chip *AL_GetChip(void); -void AL_RegisterTimbreBank(uint8_t const *timbres); -void AL_SetStereo(int const stereo); - -#endif diff --git a/source/audiolib/include/drivers.h b/source/audiolib/include/drivers.h deleted file mode 100644 index 1026e8175..000000000 --- a/source/audiolib/include/drivers.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -#ifndef DRIVERS_H -#define DRIVERS_H - -#include "sndcards.h" -#include "midifuncs.h" - -extern int ASS_PCMSoundDriver; -extern int ASS_MIDISoundDriver; -extern int ASS_EMIDICard; - -int SoundDriver_IsPCMSupported(int driver); -int SoundDriver_IsMIDISupported(int driver); - -const char *SoundDriver_GetName(int driver); - -int SoundDriver_PCM_GetError(void); -const char *SoundDriver_PCM_ErrorString(int ErrorNumber); -int SoundDriver_MIDI_GetError(void); -const char *SoundDriver_MIDI_ErrorString(int ErrorNumber); - -int SoundDriver_PCM_Init(int *mixrate, int *numchannels, void *initdata); -void SoundDriver_PCM_Shutdown(void); -int SoundDriver_PCM_BeginPlayback(char *BufferStart, int BufferSize, int NumDivisions, void (*CallBackFunc)(void)); -void SoundDriver_PCM_StopPlayback(void); -void SoundDriver_PCM_Lock(void); -void SoundDriver_PCM_Unlock(void); - -int SoundDriver_MIDI_Init(midifuncs *); -void SoundDriver_MIDI_Shutdown(void); -int SoundDriver_MIDI_StartPlayback(void (*service)(void)); -void SoundDriver_MIDI_HaltPlayback(void); -void SoundDriver_MIDI_SetTempo(int tempo, int division); -void SoundDriver_MIDI_Lock(void); -void SoundDriver_MIDI_Unlock(void); - -#endif diff --git a/source/audiolib/include/fx_man.h b/source/audiolib/include/fx_man.h deleted file mode 100644 index 05177cac8..000000000 --- a/source/audiolib/include/fx_man.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -/********************************************************************** - module: FX_MAN.H - - author: James R. Dose - date: March 17, 1994 - - Public header for FX_MAN.C - - (c) Copyright 1994 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#ifndef FX_MAN_H_ -#define FX_MAN_H_ - -#include "drivers.h" -#include -#include "limits.h" -#include "multivoc.h" - -enum FX_ERRORS -{ - FX_Warning = -2, - FX_Error = -1, - FX_Ok = 0, - FX_InvalidCard, - FX_MultiVocError, -}; - -enum FX_LOOP_HOW -{ - FX_ONESHOT = -1, - FX_LOOP = 0, -}; - -#define FX_MUSIC_PRIORITY INT_MAX - -const char *FX_ErrorString(int ErrorNumber); -int FX_Init(int numvoices, int numchannels, int mixrate, void *initdata); -int FX_Shutdown(void); -int FX_GetDevice(void); - - - -int FX_Play(char *ptr, uint32_t ptrlength, int loopstart, int loopend, int pitchoffset, - int vol, int left, int right, int priority, float volume, intptr_t callbackval); -int FX_Play3D(char *ptr, uint32_t ptrlength, int loophow, int pitchoffset, int angle, - int distance, int priority, float volume, intptr_t callbackval); -int FX_PlayRaw(char *ptr, uint32_t ptrlength, int rate, int pitchoffset, int vol, - int left, int right, int priority, float volume, intptr_t callbackval); -int FX_PlayLoopedRaw(char *ptr, uint32_t ptrlength, char *loopstart, char *loopend, int rate, - int pitchoffset, int vol, int left, int right, int priority, float volume, intptr_t callbackval); - -int FX_StartDemandFeedPlayback(void (*function)(const char** ptr, uint32_t* length), int rate, int pitchoffset, - int vol, int left, int right, int priority, fix16_t volume, uint32_t callbackval); - -int FX_SetPrintf(void(*function)(const char *, ...)); - -extern int FX_ErrorCode; -#define FX_SetErrorCode(status) FX_ErrorCode = (status); - -static FORCE_INLINE int FX_CheckMVErr(int status) -{ - if (status != MV_Ok) - { - FX_SetErrorCode(FX_MultiVocError); - status = FX_Warning; - } - - return status; -} - -static FORCE_INLINE void FX_SetCallBack(void(*function)(intptr_t)) { MV_SetCallBack(function); } -static FORCE_INLINE void FX_SetVolume(int volume) { MV_SetVolume(volume); } -static FORCE_INLINE int FX_GetVolume(void) { return MV_GetVolume(); } -static FORCE_INLINE void FX_SetReverseStereo(int setting) { MV_SetReverseStereo(setting); } -static FORCE_INLINE int FX_GetReverseStereo(void) { return MV_GetReverseStereo(); } -static FORCE_INLINE void FX_SetReverb(int reverb) { MV_SetReverb(reverb); } -static FORCE_INLINE int FX_GetMaxReverbDelay(void) { return MV_GetMaxReverbDelay(); } -static FORCE_INLINE int FX_GetReverbDelay(void) { return MV_GetReverbDelay(); } -static FORCE_INLINE void FX_SetReverbDelay(int delay) { MV_SetReverbDelay(delay); } -static FORCE_INLINE int FX_VoiceAvailable(int priority) { return MV_VoiceAvailable(priority); } -static FORCE_INLINE int FX_PauseVoice(int handle, int pause) { return FX_CheckMVErr(MV_PauseVoice(handle, pause)); } -static FORCE_INLINE int FX_EndLooping(int handle) { return FX_CheckMVErr(MV_EndLooping(handle)); } -static FORCE_INLINE int FX_SetPan(int handle, int vol, int left, int right) -{ - return FX_CheckMVErr(MV_SetPan(handle, vol, left, right)); -} -static FORCE_INLINE int FX_SetPitch(int handle, int pitchoffset) { return FX_CheckMVErr(MV_SetPitch(handle, pitchoffset)); } -static FORCE_INLINE int FX_SetFrequency(int handle, int frequency) { return FX_CheckMVErr(MV_SetFrequency(handle, frequency)); } -static FORCE_INLINE int32_t FX_GetFrequency(int32_t handle, int32_t *frequency) { return FX_CheckMVErr(MV_GetFrequency(handle, frequency)); } -static FORCE_INLINE int FX_Pan3D(int handle, int angle, int distance) -{ - return FX_CheckMVErr(MV_Pan3D(handle, angle, distance)); -} -static FORCE_INLINE int FX_SoundActive(int handle) { return MV_VoicePlaying(handle); } -static FORCE_INLINE int FX_SoundValidAndActive(int handle) { return handle > 0 && MV_VoicePlaying(handle); } -static FORCE_INLINE int FX_SoundsPlaying(void) { return MV_VoicesPlaying(); } -static FORCE_INLINE int FX_StopSound(int handle) { return FX_CheckMVErr(MV_Kill(handle)); } -static FORCE_INLINE int FX_StopAllSounds(void) { return FX_CheckMVErr(MV_KillAllVoices()); } - -#endif diff --git a/source/audiolib/include/midifuncs.h b/source/audiolib/include/midifuncs.h deleted file mode 100644 index 7b85a49b7..000000000 --- a/source/audiolib/include/midifuncs.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef __MIDIFUNCS_H -#define __MIDIFUNCS_H - -typedef struct - { - void ( *NoteOff )( int channel, int key, int velocity ); - void ( *NoteOn )( int channel, int key, int velocity ); - void ( *PolyAftertouch )( int channel, int key, int pressure ); - void ( *ControlChange )( int channel, int number, int value ); - void ( *ProgramChange )( int channel, int program ); - void ( *ChannelAftertouch )( int channel, int pressure ); - void ( *PitchBend )( int channel, int lsb, int msb ); - void ( *ReleasePatches )( void ); - void ( *LoadPatch )( int number ); - void ( *SetVolume )( int volume ); - int ( *GetVolume )( void ); - void ( *SysEx )( const unsigned char * data, int length ); - } midifuncs; - -#endif diff --git a/source/audiolib/include/multivoc.h b/source/audiolib/include/multivoc.h deleted file mode 100644 index 5828ad9d6..000000000 --- a/source/audiolib/include/multivoc.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -/********************************************************************** - file: MULTIVOC.H - - author: James R. Dose - date: December 20, 1993 - - Public header for MULTIVOC.C - - (c) Copyright 1993 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#ifndef MULTIVOC_H_ -#define MULTIVOC_H_ - -#include "compat.h" -#include "drivers.h" - -typedef enum : char -{ - FMT_UNKNOWN, - FMT_RAW, - FMT_VOC, - FMT_WAV, - FMT_SNDFILE, - FMT_ZMUSIC, - // soon to be obsolete. - FMT_VORBIS, - FMT_FLAC, - FMT_MAX -} wavefmt_t; - -#define MV_MINVOICEHANDLE 1 - -extern int MV_ErrorCode; - -enum MV_Errors -{ - MV_Error = -1, - MV_Ok = 0, - MV_NotInstalled, - MV_DriverError, - MV_NoVoices, - MV_NoMem, - MV_VoiceNotFound, - MV_InvalidFile, -}; - -extern void (*MV_Printf)(const char *fmt, ...); -extern int MV_Locked; - -static inline void MV_Lock(void) -{ - if (!MV_Locked++) - SoundDriver_PCM_Lock(); -} - -static inline void MV_Unlock(void) -{ - if (!--MV_Locked) - SoundDriver_PCM_Unlock(); - else if (MV_Locked < 0) - MV_Printf("MV_Unlock(): lockdepth < 0!\n"); -} - -const char *MV_ErrorString(int ErrorNumber); - -int MV_VoicePlaying(int handle); -int MV_KillAllVoices(void); -int MV_Kill(int handle); -int MV_VoicesPlaying(void); -int MV_VoiceAvailable(int priority); -int MV_SetPitch(int handle, int pitchoffset); -int MV_SetFrequency(int handle, int frequency); -int32_t MV_GetFrequency(int32_t handle, int32_t* frequency); -int MV_PauseVoice(int handle, int pause); -int MV_EndLooping(int handle); -int MV_SetPan(int handle, int vol, int left, int right); -int MV_Pan3D(int handle, int angle, int distance); -void MV_SetReverb(int reverb); -int MV_GetMaxReverbDelay(void); -int MV_GetReverbDelay(void); -void MV_SetReverbDelay(int delay); - -int MV_PlayVOC3D(char *ptr, uint32_t length, int loophow, int pitchoffset, int angle, int distance, - int priority, float volume, intptr_t callbackval); -int MV_PlayVOC(char *ptr, uint32_t length, int loopstart, int loopend, int pitchoffset, int vol, - int left, int right, int priority, float volume, intptr_t callbackval); - -int MV_StartDemandFeedPlayback(void (*function)(const char** ptr, uint32_t* length), int rate, - int pitchoffset, int vol, int left, int right, int priority, fix16_t volume, uint32_t callbackval); - -decltype(MV_PlayVOC3D) MV_PlayWAV3D; -decltype(MV_PlayVOC) MV_PlayWAV; -decltype(MV_PlayVOC3D) MV_PlayVorbis3D; -decltype(MV_PlayVOC) MV_PlayVorbis; -decltype(MV_PlayVOC3D) MV_PlayFLAC3D; -decltype(MV_PlayVOC) MV_PlayFLAC; - -int MV_PlayRAW(char *ptr, uint32_t length, int rate, char *loopstart, char *loopend, int pitchoffset, int vol, - int left, int right, int priority, float volume, intptr_t callbackval); - -int MV_GetPosition(int handle, int *position); -int MV_SetPosition(int handle, int position); -void MV_SetVolume(int volume); -int MV_GetVolume(void); -void MV_SetCallBack(void (*function)(intptr_t)); -void MV_SetReverseStereo(int setting); -int MV_GetReverseStereo(void); -int MV_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initdata); -int MV_Shutdown(void); -void MV_HookMusicRoutine(void (*callback)(void)); -void MV_UnhookMusicRoutine(void); - -struct MV_MusicRoutineBuffer -{ - char * buffer; - int32_t size; -}; -struct MV_MusicRoutineBuffer MV_GetMusicRoutineBuffer(void); - -static inline void MV_SetPrintf(void (*function)(const char *, ...)) { if (function) MV_Printf = function; } - -#endif diff --git a/source/audiolib/include/music.h b/source/audiolib/include/music.h deleted file mode 100644 index 1613431be..000000000 --- a/source/audiolib/include/music.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) -*/ -/********************************************************************** - module: MUSIC.H - - author: James R. Dose - date: March 25, 1994 - - Public header for MUSIC.C - - (c) Copyright 1994 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#ifndef __MUSIC_H -#define __MUSIC_H - -#include "compat.h" - -extern int MUSIC_ErrorCode; - -enum MUSIC_ERRORS -{ - MUSIC_Warning = -2, - MUSIC_Error = -1, - MUSIC_Ok = 0, - MUSIC_MidiError, -}; - -typedef struct -{ - uint32_t tickposition; - uint32_t milliseconds; - uint32_t measure; - uint32_t beat; - uint32_t tick; -} songposition; - -#define MUSIC_LoopSong ( 1 == 1 ) -#define MUSIC_PlayOnce ( !MUSIC_LoopSong ) - -#define MUSIC_SetErrorCode(status) MUSIC_ErrorCode = (status); - -extern const char *MUSIC_ErrorString(int ErrorNumber); - -int MUSIC_Init(int SoundCard); -int MUSIC_Shutdown(void); -int MIDI_GetDevice(void); -void MUSIC_SetVolume(int volume); -int MUSIC_GetVolume(void); -void MUSIC_SetLoopFlag(int loopflag); -void MUSIC_Continue(void); -void MUSIC_Pause(void); -int MUSIC_StopSong(void); -int MUSIC_PlaySong(char *song, int songsize, int loopflag, const char *fn = nullptr); -void MUSIC_Update(void); - -#endif diff --git a/source/audiolib/include/opl3.h b/source/audiolib/include/opl3.h deleted file mode 100644 index cc476c1f7..000000000 --- a/source/audiolib/include/opl3.h +++ /dev/null @@ -1,160 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2013-2019 Nuke.YKT - -This file is part of NBlood. - -NBlood is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- -// -// Nuked OPL3 emulator. -// Thanks: -// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): -// Feedback and Rhythm part calculation information. -// forums.submarine.org.uk(carbon14, opl3): -// Tremolo and phase generator calculation information. -// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): -// OPL2 ROMs. -// siliconpr0n.org(John McMaster, digshadow): -// YMF262 and VRC VII decaps and die shots. -// -// version: 1.8 -// - -#ifndef OPL_OPL3_H -#define OPL_OPL3_H - -#include - -#define OPL_WRITEBUF_SIZE 1024 -#define OPL_WRITEBUF_DELAY 2 - -typedef uintptr_t Bitu; -typedef intptr_t Bits; -typedef uint64_t Bit64u; -typedef int64_t Bit64s; -typedef uint32_t Bit32u; -typedef int32_t Bit32s; -typedef uint16_t Bit16u; -typedef int16_t Bit16s; -typedef uint8_t Bit8u; -typedef int8_t Bit8s; - -typedef struct _opl3_slot opl3_slot; -typedef struct _opl3_channel opl3_channel; -typedef struct _opl3_chip opl3_chip; - -struct _opl3_slot { - opl3_channel *channel; - opl3_chip *chip; - Bit16s out; - Bit16s fbmod; - Bit16s *mod; - Bit16s prout; - Bit16s eg_rout; - Bit16s eg_out; - Bit8u eg_inc; - Bit8u eg_gen; - Bit8u eg_rate; - Bit8u eg_ksl; - Bit8u *trem; - Bit8u reg_vib; - Bit8u reg_type; - Bit8u reg_ksr; - Bit8u reg_mult; - Bit8u reg_ksl; - Bit8u reg_tl; - Bit8u reg_ar; - Bit8u reg_dr; - Bit8u reg_sl; - Bit8u reg_rr; - Bit8u reg_wf; - Bit8u key; - Bit32u pg_reset; - Bit32u pg_phase; - Bit16u pg_phase_out; - Bit8u slot_num; -}; - -struct _opl3_channel { - opl3_slot *slots[2]; - opl3_channel *pair; - opl3_chip *chip; - Bit16s *out[4]; - Bit8u chtype; - Bit16u f_num; - Bit8u block; - Bit8u fb; - Bit8u con; - Bit8u alg; - Bit8u ksv; - Bit16u cha, chb; - Bit32s leftpan; - Bit32s rightpan; - Bit8u ch_num; -}; - -typedef struct _opl3_writebuf { - Bit64u time; - Bit16u reg; - Bit8u data; -} opl3_writebuf; - -struct _opl3_chip { - opl3_channel channel[18]; - opl3_slot slot[36]; - Bit16u timer; - Bit64u eg_timer; - Bit8u eg_timerrem; - Bit8u eg_state; - Bit8u eg_add; - Bit8u newm; - Bit8u nts; - Bit8u rhy; - Bit8u vibpos; - Bit8u vibshift; - Bit8u tremolo; - Bit8u tremolopos; - Bit8u tremoloshift; - Bit32u noise; - Bit16s zeromod; - Bit32s mixbuff[2]; - Bit8u rm_hh_bit2; - Bit8u rm_hh_bit3; - Bit8u rm_hh_bit7; - Bit8u rm_hh_bit8; - Bit8u rm_tc_bit3; - Bit8u rm_tc_bit5; - Bit8u stereoext; - Bit32s rateratio; - Bit32s samplecnt; - Bit16s oldsamples[2]; - Bit16s samples[2]; - - Bit64u writebuf_samplecnt; - Bit32u writebuf_cur; - Bit32u writebuf_last; - Bit64u writebuf_lasttime; - opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; -}; - -void OPL3_Generate(opl3_chip *chip, Bit16s *buf); -void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf); -void OPL3_Reset(opl3_chip *chip, Bit32u samplerate); -void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v); -void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v); -void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples); -#endif diff --git a/source/audiolib/include/opl3_reg.h b/source/audiolib/include/opl3_reg.h deleted file mode 100644 index 2396706d6..000000000 --- a/source/audiolib/include/opl3_reg.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright by Hannu Savolainen 1993-1996 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -// heavily modified for audiolib -// original definitions found at http://www.cs.albany.edu/~sdc/Linux/linux-2.0/drivers/sound/opl3.h -// it's from old Linux source but the license is pretty clearly 2-clause BSD. - -#ifndef opl3_reg_h__ -#define OPL3_opl3_reg_h__ - -#define OPL3_TEST_REGISTER 0x01 -#define OPL3_ENABLE_WAVE_SELECT 0x20 - -#define OPL3_TIMER1_REGISTER 0x02 -#define OPL3_TIMER2_REGISTER 0x03 -#define OPL3_TIMER_CONTROL_REGISTER 0x04 /* Left side */ -#define OPL3_IRQ_RESET 0x80 -#define OPL3_TIMER1_MASK 0x40 -#define OPL3_TIMER2_MASK 0x20 -#define OPL3_TIMER1_START 0x01 -#define OPL3_TIMER2_START 0x02 - -#define OPL3_CONNECTION_SELECT_REGISTER 0x04 /* Right side */ -#define OPL3_RIGHT_4OP_0 0x01 -#define OPL3_RIGHT_4OP_1 0x02 -#define OPL3_RIGHT_4OP_2 0x04 -#define OPL3_LEFT_4OP_0 0x08 -#define OPL3_LEFT_4OP_1 0x10 -#define OPL3_LEFT_4OP_2 0x20 - -#define OPL3_MODE_REGISTER 0x05 /* Right side */ -#define OPL3_ENABLE 0x01 -#define OPL3_OPL4_ENABLE 0x02 - -#define OPL3_KBD_SPLIT_REGISTER 0x08 /* Left side */ -#define OPL3_COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */ -#define OPL3_KEYBOARD_SPLIT 0x40 - -#define OPL3_PERCUSSION_REGISTER 0xbd /* Left side only */ -#define OPL3_TREMOLO_DEPTH 0x80 -#define OPL3_VIBRATO_DEPTH 0x40 -#define OPL3_PERCUSSION_ENABLE 0x20 -#define OPL3_BASSDRUM_ON 0x10 -#define OPL3_SNAREDRUM_ON 0x08 -#define OPL3_TOMTOM_ON 0x04 -#define OPL3_CYMBAL_ON 0x02 -#define OPL3_HIHAT_ON 0x01 - -/* - * Offsets to the register banks for operators. To get the - * register number just add the operator offset to the bank offset - * - * AM/VIB/EG/KSR/Multiple (0x20 to 0x35) - */ -#define OPL3_AM_VIB 0x20 -#define OPL3_TREMOLO_ON 0x80 -#define OPL3_VIBRATO_ON 0x40 -#define OPL3_SUSTAIN_ON 0x20 -#define OPL3_KSR 0x10 /* Key scaling rate */ -#define OPL3_MULTIPLE_MASK 0x0f /* Frequency multiplier */ - -/* - * KSL/Total level (0x40 to 0x55) - */ -#define OPL3_KSL_LEVEL 0x40 -#define OPL3_KSL_MASK 0xc0 /* Envelope scaling bits */ -#define OPL3_TOTAL_LEVEL_MASK 0x3f /* Strength (volume) of OP */ - -/* - * Attack / Decay rate (0x60 to 0x75) - */ -#define OPL3_ATTACK_DECAY 0x60 -#define OPL3_ATTACK_MASK 0xf0 -#define OPL3_DECAY_MASK 0x0f - -/* - * Sustain level / Release rate (0x80 to 0x95) - */ -#define OPL3_SUSTAIN_RELEASE 0x80 -#define OPL3_SUSTAIN_MASK 0xf0 -#define OPL3_RELEASE_MASK 0x0f - -/* - * Wave select (0xE0 to 0xF5) - */ -#define OPL3_WAVE_SELECT 0xe0 - -/* - * Offsets to the register banks for voices. Just add to the - * voice number to get the register number. - * - * F-Number low bits (0xA0 to 0xA8). - */ -#define OPL3_FNUM_LOW 0xa0 - -/* - * F-number high bits / Key on / Block (octave) (0xB0 to 0xB8) - */ -#define OPL3_KEYON_BLOCK 0xb0 -#define OPL3_KEYON_BIT 0x20 -#define OPL3_BLOCKNUM_MASK 0x1c -#define OPL3_FNUM_HIGH_MASK 0x03 - -/* - * Feedback / Connection (0xc0 to 0xc8) - * - * These registers have two new bits when the OPL-3 mode - * is selected. These bits controls connecting the voice - * to the stereo channels. For 4 OP voices this bit is - * defined in the second half of the voice (add 3 to the - * register offset). - * - * For 4 OP voices the connection bit is used in the - * both halfs (gives 4 ways to connect the operators). - */ -#define OPL3_FEEDBACK_CONNECTION 0xc0 -#define OPL3_FEEDBACK_MASK 0x0e /* Valid just for 1st OP of a voice */ -#define OPL3_CONNECTION_BIT 0x01 -#define OPL3_STEREO_BITS 0x30 /* OPL-3 only */ -#define OPL3_VOICE_TO_LEFT 0x10 -#define OPL3_VOICE_TO_RIGHT 0x20 - -#endif // opl3_reg_h__ diff --git a/source/audiolib/include/sndcards.h b/source/audiolib/include/sndcards.h deleted file mode 100644 index b272480c7..000000000 --- a/source/audiolib/include/sndcards.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -/********************************************************************** - module: SNDCARDS.H - - author: James R. Dose - date: March 31, 1994 - - Contains enumerated type definitions for sound cards. - - (c) Copyright 1994 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#ifndef __SNDCARDS_H -#define __SNDCARDS_H - -typedef enum -{ - ASS_SDL, - ASS_DirectSound, - ASS_OPL3, - ASS_WinMM, - ASS_NumSoundCards, - ASS_AutoDetect = -2 -} soundcardnames; - -#endif diff --git a/source/audiolib/src/_al_midi.h b/source/audiolib/src/_al_midi.h deleted file mode 100644 index 4de5c5f5a..000000000 --- a/source/audiolib/src/_al_midi.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef ___AL_MIDI_H -#define ___AL_MIDI_H - -#include - -#define STEREO_DETUNE 5 - -#define lobyte(num) ((uint32_t)*((char *)&(num))) -#define hibyte(num) ((uint32_t)*(((char *)&(num)) + 1)) - -#define AL_MaxVolume 127 -#define AL_DefaultChannelVolume 90 -#define AL_DefaultPitchBendRange 200 -#define AL_VoiceNotFound -1 - -#define ADLIB_PORT 0x388 - -/* Number of slots for the voices on the chip */ -#define AL_NumChipSlots 18 - -#define NUMADLIBVOICES 9 -#define NUMADLIBCHANNELS 16 - -#define NOTE_ON 0x2000 /* Used to turn note on or toggle note */ -#define NOTE_OFF 0x0000 - -#define MAX_VELOCITY 0x7f -#define MAX_OCTAVE 7 -#define MAX_NOTE (MAX_OCTAVE * 12 + 11) -#define FINETUNE_MAX 31 -#define FINETUNE_RANGE (FINETUNE_MAX + 1) - -#define PITCHBEND_CENTER 1638400 - -#define MIDI_VOLUME 7 -#define MIDI_PAN 10 -#define MIDI_DETUNE 94 -#define MIDI_ALL_NOTES_OFF 0x7B -#define MIDI_RESET_ALL_CONTROLLERS 0x79 -#define MIDI_RPN_MSB 100 -#define MIDI_RPN_LSB 101 -#define MIDI_DATAENTRY_MSB 6 -#define MIDI_DATAENTRY_LSB 38 -#define MIDI_PITCHBEND_RPN 0 - -/* Definition of octave information to be ORed onto F-Number */ - -enum octaves -{ - OCTAVE_0 = 0x0000, - OCTAVE_1 = 0x0400, - OCTAVE_2 = 0x0800, - OCTAVE_3 = 0x0C00, - OCTAVE_4 = 0x1000, - OCTAVE_5 = 0x1400, - OCTAVE_6 = 0x1800, - OCTAVE_7 = 0x1C00 -}; - -typedef struct AdLibVoice -{ - struct AdLibVoice *next; - struct AdLibVoice *prev; - - uint32_t num; - uint32_t key; - uint32_t velocity; - uint32_t channel; - uint32_t pitchleft; - uint32_t pitchright; - int timbre; - int port; - uint32_t status; -} AdLibVoice; - -typedef struct -{ - AdLibVoice *start; - AdLibVoice *end; -} AdLibVoiceList; - -typedef struct -{ - AdLibVoiceList Voices; - - int Timbre; - int Pitchbend; - int KeyOffset; - uint32_t KeyDetune; - uint32_t Volume; - uint32_t EffectiveVolume; - int Pan; - int Detune; - uint32_t RPN; - int16_t PitchBendRange; - int16_t PitchBendSemiTones; - int16_t PitchBendHundreds; -} AdLibChannel; - -static int AL_Init(int rate); -static void AL_NoteOff(int channel, int key, int velocity); -static void AL_NoteOn(int channel, int key, int vel); -static void AL_ControlChange(int channel, int type, int data); -static void AL_ProgramChange(int channel, int patch); -static void AL_SetPitchBend(int channel, int lsb, int msb); - -#endif diff --git a/source/audiolib/src/_midi.h b/source/audiolib/src/_midi.h deleted file mode 100644 index 160bdd812..000000000 --- a/source/audiolib/src/_midi.h +++ /dev/null @@ -1,156 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2010-2019 EDuke32 developers and contributors -Copyright (C) 2019 Nuke.YKT - -This file is part of NBlood. - -NBlood is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- - -#ifndef ___MIDI_H -#define ___MIDI_H -#include "compat.h" - -#define RELATIVE_BEAT(measure, beat, tick) ((tick) + ((beat) << 9) + ((measure) << 16)) - -//Bobby Prince thinks this may be 100 -//#define GENMIDI_DefaultVolume 100 -#define GENMIDI_DefaultVolume 90 - -#define MAX_FORMAT 1 - -#define NUM_MIDI_CHANNELS 16 - -#define TIME_PRECISION 16 - -#define MIDI_HEADER_SIGNATURE 0x6468544d // "MThd" -#define MIDI_TRACK_SIGNATURE 0x6b72544d // "MTrk" - -#define MIDI_VOLUME 7 -#define MIDI_PAN 10 -#define MIDI_DETUNE 94 -#define MIDI_RHYTHM_CHANNEL 9 -#define MIDI_BANK_SELECT_MSB 0 -#define MIDI_BANK_SELECT_LSB 32 -#define MIDI_RPN_MSB 100 -#define MIDI_RPN_LSB 101 -#define MIDI_DATAENTRY_MSB 6 -#define MIDI_DATAENTRY_LSB 38 -#define MIDI_PITCHBEND_MSB 0 -#define MIDI_PITCHBEND_LSB 0 -#define MIDI_RUNNING_STATUS 0x80 -#define MIDI_NOTE_OFF 0x8 -#define MIDI_NOTE_ON 0x9 -#define MIDI_POLY_AFTER_TCH 0xA -#define MIDI_CONTROL_CHANGE 0xB -#define MIDI_PROGRAM_CHANGE 0xC -#define MIDI_AFTER_TOUCH 0xD -#define MIDI_PITCH_BEND 0xE -#define MIDI_SPECIAL 0xF -#define MIDI_SYSEX 0xF0 -#define MIDI_SYSEX_CONTINUE 0xF7 -#define MIDI_META_EVENT 0xFF -#define MIDI_END_OF_TRACK 0x2F -#define MIDI_HOLD1 0x40 -#define MIDI_SOSTENUTO 0x42 -#define MIDI_TEMPO_CHANGE 0x51 -#define MIDI_TIME_SIGNATURE 0x58 -#define MIDI_REVERB 0x5b -#define MIDI_CHORUS 0x5d -#define MIDI_ALL_SOUNDS_OFF 0x78 -#define MIDI_RESET_ALL_CONTROLLERS 0x79 -#define MIDI_ALL_NOTES_OFF 0x7b -#define MIDI_MONO_MODE_ON 0x7E -#define MIDI_SYSTEM_RESET 0xFF - -#define GET_NEXT_EVENT( track, data ) do { \ - ( data ) = *( track )->pos; \ - ( track )->pos += 1; \ -} while (0) - -#define GET_MIDI_CHANNEL( event ) ( ( event ) & 0xf ) -#define GET_MIDI_COMMAND( event ) ( ( event ) >> 4 ) - -#define EMIDI_INFINITE -1 -#define EMIDI_END_LOOP_VALUE 127 -#define EMIDI_ALL_CARDS 127 -#define EMIDI_INCLUDE_TRACK 110 -#define EMIDI_EXCLUDE_TRACK 111 -#define EMIDI_PROGRAM_CHANGE 112 -#define EMIDI_VOLUME_CHANGE 113 -#define EMIDI_CONTEXT_START 114 -#define EMIDI_CONTEXT_END 115 -#define EMIDI_LOOP_START 116 -#define EMIDI_LOOP_END 117 -#define EMIDI_SONG_LOOP_START 118 -#define EMIDI_SONG_LOOP_END 119 - -#define EMIDI_GeneralMIDI 0 -#define EMIDI_SoundBlaster 4 -#define EMIDI_AdLib 7 - -#define EMIDI_AffectsCurrentCard(c, type) (((c) == EMIDI_ALL_CARDS) || ((c) == (type))) -#define EMIDI_NUM_CONTEXTS 7 - -typedef struct -{ - char *pos; - char *loopstart; - int16_t loopcount; - int16_t RunningStatus; - unsigned time; - int FPSecondsPerTick; - int16_t tick; - int16_t beat; - int16_t measure; - int16_t BeatsPerMeasure; - int16_t TicksPerBeat; - int16_t TimeBase; - int delay; - int16_t active; -} songcontext; - -typedef struct -{ - char *start; - char *pos; - - int delay; - int16_t active; - int16_t RunningStatus; - - int16_t currentcontext; - songcontext context[EMIDI_NUM_CONTEXTS]; - - char EMIDI_IncludeTrack; - char EMIDI_ProgramChange; - char EMIDI_VolumeChange; -} track; - -static int _MIDI_ReadNumber(void *from, size_t size); -static int _MIDI_ReadDelta(track *ptr); -static void _MIDI_ResetTracks(void); -static void _MIDI_AdvanceTick(void); -static void _MIDI_MetaEvent(track *Track); -static void _MIDI_SysEx(track *Track); -static int _MIDI_InterpretControllerInfo(track *Track, int TimeSet, int channel, int c1, int c2); -static int _MIDI_SendControlChange(int channel, int c1, int c2); -static void _MIDI_SetChannelVolume(int channel, int volume); -static void _MIDI_SendChannelVolumes(void); -static void _MIDI_InitEMIDI(void); - -#endif diff --git a/source/audiolib/src/_multivc.h b/source/audiolib/src/_multivc.h deleted file mode 100644 index 79d55056c..000000000 --- a/source/audiolib/src/_multivc.h +++ /dev/null @@ -1,295 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -/********************************************************************** - file: _MULTIVC.H - - author: James R. Dose - date: December 20, 1993 - - Private header for MULTIVOC.C - - (c) Copyright 1993 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#ifndef MULTIVC_H_ -#define MULTIVC_H_ - -#include "multivoc.h" - -#define VOC_8BIT 0x0 -#define VOC_16BIT 0x4 - -#define T_SIXTEENBIT_STEREO 0 -#define T_MONO 1 -#define T_16BITSOURCE 2 -#define T_STEREOSOURCE 4 -#define T_DEFAULT T_SIXTEENBIT_STEREO - -#define MV_MAXPANPOSITION 127 /* formerly 31 */ -#define MV_NUMPANPOSITIONS ( MV_MAXPANPOSITION + 1 ) -#define MV_MAXTOTALVOLUME 255 -#define MV_MAXVOLUME 127 /* formerly 63 */ - -// mirrors FX_MUSIC_PRIORITY from fx_man.h -#define MV_MUSIC_PRIORITY INT_MAX - -#define MIX_VOLUME(volume) ((max(0, min((volume), 255)) * (MV_MAXVOLUME + 1)) >> 8) - -extern float MV_GlobalVolume; -extern float MV_VolumeSmooth; - -static FORCE_INLINE float SMOOTH_VOLUME(float const volume, float const dest) -{ - return volume + (dest - volume) * MV_VolumeSmooth; -} - -template -static inline conditional_t< is_signed::value, make_unsigned_t, make_signed_t > FLIP_SIGN(T src) -{ - static constexpr make_unsigned_t msb = ((make_unsigned_t)1) << (sizeof(T) * CHAR_BIT - 1u); - return src ^ msb; -} - -template -static inline enable_if_t::value, T> SCALE_SAMPLE(T src, float volume) -{ - return (T)Blrintf((float)src * volume); -} - -template -static inline T CONVERT_SAMPLE_FROM_SIGNED(int src); - -template<> -inline int16_t CONVERT_SAMPLE_FROM_SIGNED(int src) -{ - return src; -} - -template -static inline int CONVERT_SAMPLE_TO_SIGNED(T src); - -template<> -inline int CONVERT_SAMPLE_TO_SIGNED(int16_t src) -{ - return src; -} - -template -static inline int CONVERT_LE_SAMPLE_TO_SIGNED(S src); - -template<> -inline int CONVERT_LE_SAMPLE_TO_SIGNED(uint8_t src) -{ - return FLIP_SIGN(src) << 8; -} - -template<> -inline int CONVERT_LE_SAMPLE_TO_SIGNED(int16_t src) -{ - return B_LITTLE16(src); -} - -template -static int CLAMP_SAMPLE(int src); - -template<> -inline int CLAMP_SAMPLE(int src) -{ - return clamp(src, INT16_MIN, INT16_MAX); -} - -template -static T MIX_SAMPLES(int signed_sample, T untouched_sample) -{ - return CONVERT_SAMPLE_FROM_SIGNED(CLAMP_SAMPLE(signed_sample + CONVERT_SAMPLE_TO_SIGNED(untouched_sample))); -} - -struct split16_t -{ - explicit split16_t(uint16_t x) : v{x} {} - - uint8_t l() const - { - return (v & 0x00FFu); - } - uint8_t h() const - { - return (v & 0xFF00u) >> CHAR_BIT; - } - -private: - uint16_t v; -}; - -#define MV_MIXBUFFERSIZE 256 -#define MV_NUMBEROFBUFFERS 32 -#define MV_TOTALBUFFERSIZE ( MV_MIXBUFFERSIZE * MV_NUMBEROFBUFFERS ) - -typedef enum : bool -{ - NoMoreData, - KeepPlaying -} playbackstatus; - - -typedef struct VoiceNode -{ - struct VoiceNode *next; - struct VoiceNode *prev; - - playbackstatus (*GetSound)(struct VoiceNode *); - - uint32_t (*mix)(struct VoiceNode *, uint32_t); - - void (*DemandFeed)(const char** ptr, uint32_t* length); - - const char *sound; - - float LeftVolume, LeftVolumeDest; - float RightVolume, RightVolumeDest; - - void *rawdataptr; - - const char *NextBlock; - const char *LoopStart; - const char *LoopEnd; - - wavefmt_t wavetype; - char bits; - char channels; - - float volume; - - int LoopCount; - uint32_t LoopSize; - uint32_t BlockLength; - - int ptrlength; // ptrlength-1 is the max permissible index for rawdataptr - - uint32_t PitchScale; - uint32_t FixedPointBufferSize; - - uint32_t length; - uint32_t SamplingRate; - uint32_t RateScale; - uint32_t position; - int Paused; - - int handle; - int priority; - - intptr_t callbackval; -} VoiceNode; - -typedef struct -{ - uint8_t left; - uint8_t right; -} Pan; - -typedef struct -{ - char RIFF[4]; - uint32_t file_size; - char WAVE[4]; - char fmt[4]; - uint32_t format_size; -} riff_header; - -typedef struct -{ - uint16_t wFormatTag; - uint16_t nChannels; - uint32_t nSamplesPerSec; - uint32_t nAvgBytesPerSec; - uint16_t nBlockAlign; - uint16_t nBitsPerSample; -} format_header; - -typedef struct -{ - uint8_t DATA[4]; - uint32_t size; -} data_header; - -extern Pan MV_PanTable[ MV_NUMPANPOSITIONS ][ MV_MAXVOLUME + 1 ]; -extern int MV_ErrorCode; -extern int MV_Installed; -extern int MV_MixRate; -extern char *MV_MusicBuffer; -extern int MV_BufferSize; - -extern int MV_MIDIRenderTempo; -extern int MV_MIDIRenderTimer; - -static FORCE_INLINE int MV_SetErrorCode(int status) -{ - MV_ErrorCode = status; - return MV_Error; -} - -void MV_PlayVoice(VoiceNode *voice); - -VoiceNode *MV_AllocVoice(int priority); - -void MV_SetVoiceMixMode(VoiceNode *voice); -void MV_SetVoiceVolume(VoiceNode *voice, int vol, int left, int right, float volume); -void MV_SetVoicePitch(VoiceNode *voice, uint32_t rate, int pitchoffset); - -int MV_GetVorbisPosition(VoiceNode *voice); -void MV_SetVorbisPosition(VoiceNode *voice, int position); -int MV_GetFLACPosition(VoiceNode *voice); -void MV_SetFLACPosition(VoiceNode *voice, int position); -int MV_GetXAPosition(VoiceNode *voice); -void MV_SetXAPosition(VoiceNode *voice, int position); -int MV_GetXMPPosition(VoiceNode *voice); -void MV_SetXMPPosition(VoiceNode *voice, int position); - -void MV_ReleaseVorbisVoice(VoiceNode *voice); -void MV_ReleaseZMusicVoice(VoiceNode* voice); -void MV_ReleaseFLACVoice(VoiceNode *voice); -void MV_ReleaseXAVoice(VoiceNode *voice); -void MV_ReleaseXMPVoice(VoiceNode *voice); - -// implemented in mix.c -template uint32_t MV_MixMono(struct VoiceNode * const voice, uint32_t length); -template uint32_t MV_MixStereo(struct VoiceNode * const voice, uint32_t length); -template void MV_Reverb(char const *src, char * const dest, const float volume, int count); - -// implemented in mixst.c -template uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length); -template uint32_t MV_MixStereoStereo(struct VoiceNode * const voice, uint32_t length); - -extern char *MV_MixDestination; // pointer to the next output sample -extern int MV_SampleSize; -extern int MV_RightChannelOffset; - -#define loopStartTagCount 3 -extern const char *loopStartTags[loopStartTagCount]; -#define loopEndTagCount 2 -extern const char *loopEndTags[loopEndTagCount]; -#define loopLengthTagCount 2 -extern const char *loopLengthTags[loopLengthTagCount]; - -#if defined __POWERPC__ || defined GEKKO -# define BIGENDIAN -#endif - -#endif diff --git a/source/audiolib/src/driver_adlib.cpp b/source/audiolib/src/driver_adlib.cpp deleted file mode 100644 index aefb10bc5..000000000 --- a/source/audiolib/src/driver_adlib.cpp +++ /dev/null @@ -1,776 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -/********************************************************************** - module: AL_MIDI.C - - author: James R. Dose - date: April 1, 1994 - - Low level routines to support General MIDI music on AdLib compatible - cards. - - (c) Copyright 1994 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#include "driver_adlib.h" - -#include "_al_midi.h" -#include "_multivc.h" -#include "compat.h" -#include "midi.h" -#include "midifuncs.h" -#include "opl3.h" -#include "opl3_reg.h" -#include "c_cvars.h" - -CUSTOM_CVARD(Bool, mus_al_stereo, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enable/disable OPL3 stereo mode") -{ - AL_Stereo = self; - AL_SetStereo(AL_Stereo); -} - -CVARD(Bool, mus_al_additivemode, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable alternate additive AdLib timbre mode") - - -enum -{ - AdLibErr_Warning = -2, - AdLibErr_Error = -1, - AdLibErr_Ok = 0, -}; - -static void AL_Shutdown(void); -static int ErrorCode; - -int AdLibDrv_GetError(void) { return ErrorCode; } - -const char *AdLibDrv_ErrorString(int const ErrorNumber) -{ - const char *ErrorString; - - switch( ErrorNumber ) - { - case AdLibErr_Warning : - case AdLibErr_Error : - ErrorString = AdLibDrv_ErrorString( ErrorCode ); - break; - - case AdLibErr_Ok : - ErrorString = "AdLib ok."; - break; - - default: - ErrorString = "Unknown AdLib error."; - break; - } - - return ErrorString; -} - -int AdLibDrv_MIDI_Init(midifuncs * const funcs) -{ - AdLibDrv_MIDI_Shutdown(); - Bmemset(funcs, 0, sizeof(midifuncs)); - - funcs->NoteOff = AL_NoteOff; - funcs->NoteOn = AL_NoteOn; - funcs->PolyAftertouch = nullptr; - funcs->ControlChange = AL_ControlChange; - funcs->ProgramChange = AL_ProgramChange; - funcs->ChannelAftertouch = nullptr; - funcs->PitchBend = AL_SetPitchBend; - - return AdLibErr_Ok; -} - -void AdLibDrv_MIDI_HaltPlayback(void) { MV_UnhookMusicRoutine(); } - -void AdLibDrv_MIDI_Shutdown(void) -{ - AdLibDrv_MIDI_HaltPlayback(); - AL_Shutdown(); -} - -int AdLibDrv_MIDI_StartPlayback(void (*service)(void)) -{ - AdLibDrv_MIDI_HaltPlayback(); - - AL_Init(MV_MixRate); - MV_HookMusicRoutine(service); - - return MIDI_Ok; -} - -void AdLibDrv_MIDI_SetTempo(int const tempo, int const division) -{ - MV_MIDIRenderTempo = tempo * division / 60; - MV_MIDIRenderTimer = 0; -} - -static opl3_chip chip; - -opl3_chip *AL_GetChip(void) { return &chip; } - -static uint32_t constexpr OctavePitch[MAX_OCTAVE+1] = { - OCTAVE_0, OCTAVE_1, OCTAVE_2, OCTAVE_3, OCTAVE_4, OCTAVE_5, OCTAVE_6, OCTAVE_7, -}; - -static uint32_t NoteMod12[MAX_NOTE+1]; -static uint32_t NoteDiv12[MAX_NOTE+1]; - -// Pitch table - -//static unsigned NotePitch[ FINETUNE_MAX+1 ][ 12 ] = -// { -// { C, C_SHARP, D, D_SHARP, E, F, F_SHARP, G, G_SHARP, A, A_SHARP, B }, -// }; - -static uint32_t constexpr NotePitch[FINETUNE_MAX+1][12] = { - { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287 }, - { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x242, 0x264, 0x288 }, - { 0x158, 0x16c, 0x182, 0x199, 0x1b1, 0x1cb, 0x1e6, 0x203, 0x221, 0x243, 0x265, 0x289 }, - { 0x158, 0x16c, 0x183, 0x19a, 0x1b2, 0x1cc, 0x1e7, 0x204, 0x222, 0x244, 0x266, 0x28a }, - { 0x159, 0x16d, 0x183, 0x19a, 0x1b3, 0x1cd, 0x1e8, 0x205, 0x223, 0x245, 0x267, 0x28b }, - { 0x15a, 0x16e, 0x184, 0x19b, 0x1b3, 0x1ce, 0x1e9, 0x206, 0x224, 0x246, 0x268, 0x28c }, - { 0x15a, 0x16e, 0x185, 0x19c, 0x1b4, 0x1ce, 0x1ea, 0x207, 0x225, 0x247, 0x269, 0x28e }, - { 0x15b, 0x16f, 0x185, 0x19d, 0x1b5, 0x1cf, 0x1eb, 0x208, 0x226, 0x248, 0x26a, 0x28f }, - { 0x15b, 0x170, 0x186, 0x19d, 0x1b6, 0x1d0, 0x1ec, 0x209, 0x227, 0x249, 0x26b, 0x290 }, - { 0x15c, 0x170, 0x187, 0x19e, 0x1b7, 0x1d1, 0x1ec, 0x20a, 0x228, 0x24a, 0x26d, 0x291 }, - { 0x15d, 0x171, 0x188, 0x19f, 0x1b7, 0x1d2, 0x1ed, 0x20b, 0x229, 0x24b, 0x26e, 0x292 }, - { 0x15d, 0x172, 0x188, 0x1a0, 0x1b8, 0x1d3, 0x1ee, 0x20c, 0x22a, 0x24c, 0x26f, 0x293 }, - { 0x15e, 0x172, 0x189, 0x1a0, 0x1b9, 0x1d4, 0x1ef, 0x20d, 0x22b, 0x24d, 0x270, 0x295 }, - { 0x15f, 0x173, 0x18a, 0x1a1, 0x1ba, 0x1d4, 0x1f0, 0x20e, 0x22c, 0x24e, 0x271, 0x296 }, - { 0x15f, 0x174, 0x18a, 0x1a2, 0x1bb, 0x1d5, 0x1f1, 0x20f, 0x22d, 0x24f, 0x272, 0x297 }, - { 0x160, 0x174, 0x18b, 0x1a3, 0x1bb, 0x1d6, 0x1f2, 0x210, 0x22e, 0x250, 0x273, 0x298 }, - { 0x161, 0x175, 0x18c, 0x1a3, 0x1bc, 0x1d7, 0x1f3, 0x211, 0x22f, 0x251, 0x274, 0x299 }, - { 0x161, 0x176, 0x18c, 0x1a4, 0x1bd, 0x1d8, 0x1f4, 0x212, 0x230, 0x252, 0x276, 0x29b }, - { 0x162, 0x176, 0x18d, 0x1a5, 0x1be, 0x1d9, 0x1f5, 0x212, 0x231, 0x254, 0x277, 0x29c }, - { 0x162, 0x177, 0x18e, 0x1a6, 0x1bf, 0x1d9, 0x1f5, 0x213, 0x232, 0x255, 0x278, 0x29d }, - { 0x163, 0x178, 0x18f, 0x1a6, 0x1bf, 0x1da, 0x1f6, 0x214, 0x233, 0x256, 0x279, 0x29e }, - { 0x164, 0x179, 0x18f, 0x1a7, 0x1c0, 0x1db, 0x1f7, 0x215, 0x235, 0x257, 0x27a, 0x29f }, - { 0x164, 0x179, 0x190, 0x1a8, 0x1c1, 0x1dc, 0x1f8, 0x216, 0x236, 0x258, 0x27b, 0x2a1 }, - { 0x165, 0x17a, 0x191, 0x1a9, 0x1c2, 0x1dd, 0x1f9, 0x217, 0x237, 0x259, 0x27c, 0x2a2 }, - { 0x166, 0x17b, 0x192, 0x1aa, 0x1c3, 0x1de, 0x1fa, 0x218, 0x238, 0x25a, 0x27e, 0x2a3 }, - { 0x166, 0x17b, 0x192, 0x1aa, 0x1c3, 0x1df, 0x1fb, 0x219, 0x239, 0x25b, 0x27f, 0x2a4 }, - { 0x167, 0x17c, 0x193, 0x1ab, 0x1c4, 0x1e0, 0x1fc, 0x21a, 0x23a, 0x25c, 0x280, 0x2a6 }, - { 0x168, 0x17d, 0x194, 0x1ac, 0x1c5, 0x1e0, 0x1fd, 0x21b, 0x23b, 0x25d, 0x281, 0x2a7 }, - { 0x168, 0x17d, 0x194, 0x1ad, 0x1c6, 0x1e1, 0x1fe, 0x21c, 0x23c, 0x25e, 0x282, 0x2a8 }, - { 0x169, 0x17e, 0x195, 0x1ad, 0x1c7, 0x1e2, 0x1ff, 0x21d, 0x23d, 0x260, 0x283, 0x2a9 }, - { 0x16a, 0x17f, 0x196, 0x1ae, 0x1c8, 0x1e3, 0x1ff, 0x21e, 0x23e, 0x261, 0x284, 0x2ab }, - { 0x16a, 0x17f, 0x197, 0x1af, 0x1c8, 0x1e4, 0x200, 0x21f, 0x23f, 0x262, 0x286, 0x2ac } -}; - -// Slot numbers as a function of the voice and the operator. -// ( melodic only) - -static int constexpr slotVoice[NUMADLIBVOICES][2] = { - { 0, 3 }, // voice 0 - { 1, 4 }, // 1 - { 2, 5 }, // 2 - { 6, 9 }, // 3 - { 7, 10 }, // 4 - { 8, 11 }, // 5 - { 12, 15 }, // 6 - { 13, 16 }, // 7 - { 14, 17 }, // 8 -}; - -static int VoiceLevel[AL_NumChipSlots][2]; -static int VoiceKsl[AL_NumChipSlots][2]; - -// This table gives the offset of each slot within the chip. -// offset = fn( slot) - -static int8_t constexpr offsetSlot[AL_NumChipSlots] = { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 }; - -static int VoiceReserved[NUMADLIBVOICES * 2]; - -static AdLibVoice Voice[NUMADLIBVOICES * 2]; -static AdLibVoiceList Voice_Pool; - -static AdLibChannel Channel[NUMADLIBCHANNELS]; - -static int constexpr AL_LeftPort = ADLIB_PORT; -static int constexpr AL_RightPort = ADLIB_PORT + 2; - -static int constexpr AL_MaxMidiChannel = ARRAY_SIZE(Channel); - -int AL_Stereo = TRUE; - -int AL_PostAmp = 3; - -// TODO: clean up this shit... -#define OFFSET(structure, offset) (*((char **)&(structure)[offset])) - -#define LL_AddToTail(type, listhead, node) \ - LL_AddNode((char *)(node), (char **)&((listhead)->end), (char **)&((listhead)->start), (intptr_t) & ((type *)0)->prev, \ - (intptr_t) & ((type *)0)->next) - -#define LL_Remove(type, listhead, node) \ - LL_RemoveNode((char *)(node), (char **)&((listhead)->start), (char **)&((listhead)->end), (intptr_t) & ((type *)0)->next, \ - (intptr_t) & ((type *)0)->prev) - -static void LL_RemoveNode(char *item, char **head, char **tail, intptr_t next, intptr_t prev) -{ - if (OFFSET(item, prev) == nullptr) - *head = OFFSET(item, next); - else - OFFSET(OFFSET(item, prev), next) = OFFSET(item, next); - - if (OFFSET(item, next) == nullptr) - *tail = OFFSET(item, prev); - else - OFFSET(OFFSET(item, next), prev) = OFFSET(item, prev); - - OFFSET(item, next) = nullptr; - OFFSET(item, prev) = nullptr; -} - -static void LL_AddNode(char *item, char **head, char **tail, intptr_t next, intptr_t prev) -{ - OFFSET(item, prev) = nullptr; - OFFSET(item, next) = *head; - - if (*head) - OFFSET(*head, prev) = item; - else - *tail = item; - - *head = item; -} - - -static void AL_SendOutputToPort(int const port, int const reg, int const data) -{ - OPL3_WriteRegBuffered(&chip, (Bit16u)(reg + ((port & 2) << 7)), (Bit8u)data); -} - - -static void AL_SendOutput(int const voice, int const reg, int const data) -{ - AL_SendOutputToPort(voice ? AL_LeftPort : AL_RightPort, reg, data); -} - - -static void AL_SetVoiceTimbre(int const voice) -{ - int const channel = Voice[voice].channel; - int const patch = (channel == 9) ? Voice[voice].key + 128 : Channel[channel].Timbre; - - if (Voice[voice].timbre == patch) - return; - - Voice[voice].timbre = patch; - - auto const timbre = &ADLIB_TimbreBank[patch]; - - int const port = Voice[voice].port; - int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; - int slot = slotVoice[voc][0]; - int off = offsetSlot[slot]; - - VoiceLevel[slot][port] = OPL3_TOTAL_LEVEL_MASK - (timbre->Level[0] & OPL3_TOTAL_LEVEL_MASK); - VoiceKsl[slot][port] = timbre->Level[0] & OPL3_KSL_MASK; - - AL_SendOutput(port, OPL3_FNUM_LOW + voc, 0); - AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, 0); - - // Let voice clear the release - AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, 0xff); - - AL_SendOutput(port, OPL3_ATTACK_DECAY + off, timbre->Env1[0]); - AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, timbre->Env2[0]); - AL_SendOutput(port, OPL3_ENABLE_WAVE_SELECT + off, timbre->SAVEK[0]); - AL_SendOutput(port, OPL3_WAVE_SELECT + off, timbre->Wave[0]); - - AL_SendOutput(port, OPL3_KSL_LEVEL + off, timbre->Level[0]); - slot = slotVoice[voc][1]; - - AL_SendOutput(port, OPL3_FEEDBACK_CONNECTION + voc, (timbre->Feedback & OPL3_FEEDBACK_MASK) | OPL3_STEREO_BITS); - - off = offsetSlot[slot]; - - VoiceLevel[slot][port] = OPL3_TOTAL_LEVEL_MASK - (timbre->Level[1] & OPL3_TOTAL_LEVEL_MASK); - VoiceKsl[slot][port] = timbre->Level[1] & OPL3_KSL_MASK; - - AL_SendOutput(port, OPL3_KSL_LEVEL + off, OPL3_TOTAL_LEVEL_MASK); - - // Let voice clear the release - AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, 0xff); - - AL_SendOutput(port, OPL3_ATTACK_DECAY + off, timbre->Env1[1]); - AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, timbre->Env2[1]); - AL_SendOutput(port, OPL3_ENABLE_WAVE_SELECT + off, timbre->SAVEK[1]); - AL_SendOutput(port, OPL3_WAVE_SELECT + off, timbre->Wave[1]); -} - - -static void AL_SetVoiceVolume(int const voice) -{ - int const channel = Voice[voice].channel; - auto const timbre = &ADLIB_TimbreBank[Voice[voice].timbre]; - int const velocity = min(Voice[voice].velocity + timbre->Velocity, MAX_VELOCITY); - - int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; - int const slot = slotVoice[voc][1]; - int const port = Voice[voice].port; - - // amplitude - auto t1 = (uint32_t)VoiceLevel[slot][port] * (velocity + 0x80); - t1 = (Channel[channel].Volume * t1) >> 15; - - uint32_t volume = t1 ^ OPL3_TOTAL_LEVEL_MASK; - volume |= (uint32_t)VoiceKsl[slot][port]; - - AL_SendOutput(port, OPL3_KSL_LEVEL + offsetSlot[slot], volume); - - // Check if this timbre is Additive - if (timbre->Feedback & 0x01) - { - int const slot = slotVoice[voc][0]; - uint32_t t2; - - // amplitude - if (mus_al_additivemode) - t1 = (uint32_t)VoiceLevel[slot][port] * (velocity + 0x80); - - t2 = (Channel[channel].Volume * t1) >> 15; - - volume = t2 ^ OPL3_TOTAL_LEVEL_MASK; - volume |= (uint32_t)VoiceKsl[slot][port]; - - AL_SendOutput(port, OPL3_KSL_LEVEL + offsetSlot[slot], volume); - } -} - - -static int AL_AllocVoice(void) -{ - if (!Voice_Pool.start) - return AL_VoiceNotFound; - - int const voice = Voice_Pool.start->num; - LL_Remove(AdLibVoice, &Voice_Pool, &Voice[voice]); - return voice; -} - - -static int AL_GetVoice(int const channel, int const key) -{ - auto const *voice = Channel[channel].Voices.start; - - while (voice != nullptr) - { - if (voice->key == (uint32_t)key) - return voice->num; - voice = voice->next; - } - - return AL_VoiceNotFound; -} - - -static void AL_SetVoicePitch(int const voice) -{ - int const port = Voice[voice].port; - int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; - int const channel = Voice[voice].channel; - - int patch, note; - - if (channel == 9) - { - patch = Voice[voice].key + 128; - note = ADLIB_TimbreBank[patch].Transpose; - } - else - { - patch = Channel[channel].Timbre; - note = Voice[voice].key + ADLIB_TimbreBank[patch].Transpose; - } - - note += Channel[channel].KeyOffset - 12; - note = clamp(note, 0, MAX_NOTE); - - int detune = Channel[channel].KeyDetune; - - int ScaleNote = NoteMod12[note]; - int Octave = NoteDiv12[note]; - - int pitch = OctavePitch[Octave] | NotePitch[detune][ScaleNote]; - - Voice[voice].pitchleft = pitch; - - pitch |= Voice[voice].status; - - AL_SendOutput(port, OPL3_FNUM_LOW + voc, pitch); - AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, pitch >> 8); -} - -static void AL_SetVoicePan(int const voice) -{ - int const port = Voice[voice].port; - int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; - int const channel = Voice[voice].channel; - - if (AL_Stereo) - AL_SendOutput(port, 0xD0 + voc, Channel[channel].Pan << 1); -} - - -static void AL_SetChannelVolume(int const channel, int const volume) -{ - Channel[channel].Volume = clamp(volume, 0, AL_MaxVolume); - - auto voice = Channel[channel].Voices.start; - - while (voice != nullptr) - { - AL_SetVoiceVolume(voice->num); - voice = voice->next; - } -} - - -static void AL_SetChannelPan(int const channel, int const pan) -{ - // Don't pan drum sounds - if (channel != 9) - Channel[channel].Pan = pan; - - auto voice = Channel[channel].Voices.start; - while (voice != nullptr) - { - AL_SetVoicePan(voice->num); - voice = voice->next; - } -} - - -static void AL_SetChannelDetune(int const channel, int const detune) { Channel[channel].Detune = detune; } - - -static void AL_ResetVoices(void) -{ - Voice_Pool.start = nullptr; - Voice_Pool.end = nullptr; - - int const numvoices = NUMADLIBVOICES * 2; - - for (int index = 0; index < numvoices; index++) - { - if (VoiceReserved[index] == FALSE) - { - Voice[index].num = index; - Voice[index].key = 0; - Voice[index].velocity = 0; - Voice[index].channel = -1; - Voice[index].timbre = -1; - Voice[index].port = (index < NUMADLIBVOICES) ? 0 : 1; - Voice[index].status = NOTE_OFF; - LL_AddToTail(AdLibVoice, &Voice_Pool, &Voice[index]); - } - } - - for (int index = 0; index < NUMADLIBCHANNELS; index++) - { - Channel[index] = {}; - Channel[index].Volume = AL_DefaultChannelVolume; - Channel[index].Pan = 64; - Channel[index].PitchBendRange = AL_DefaultPitchBendRange; - Channel[index].PitchBendSemiTones = AL_DefaultPitchBendRange / 100; - Channel[index].PitchBendHundreds = AL_DefaultPitchBendRange % 100; - } -} - - -static void AL_CalcPitchInfo(void) -{ - // int finetune; - // double detune; - - for (int note = 0; note <= MAX_NOTE; note++) - { - NoteMod12[note] = note % 12; - NoteDiv12[note] = note / 12; - } - - // for( finetune = 1; finetune <= FINETUNE_MAX; finetune++ ) - // { - // detune = pow( 2, ( double )finetune / ( 12.0 * FINETUNE_RANGE ) ); - // for( note = 0; note < 12; note++ ) - // { - // NotePitch[ finetune ][ note ] = ( ( double )NotePitch[ 0 ][ note ] * detune ); - // } - // } -} - - -static void AL_FlushCard(int const port) -{ - for (int i = 0; i < NUMADLIBVOICES; i++) - { - if (VoiceReserved[i]) - continue; - - auto slot1 = offsetSlot[slotVoice[i][0]]; - auto slot2 = offsetSlot[slotVoice[i][1]]; - - AL_SendOutputToPort(port, OPL3_FNUM_LOW + i, 0); - AL_SendOutputToPort(port, OPL3_KEYON_BLOCK + i, 0); - - AL_SendOutputToPort(port, OPL3_WAVE_SELECT + slot1, 0); - AL_SendOutputToPort(port, OPL3_WAVE_SELECT + slot2, 0); - - // Set the envelope to be fast and quiet - AL_SendOutputToPort(port, OPL3_ATTACK_DECAY + slot1, 0xff); - AL_SendOutputToPort(port, OPL3_ATTACK_DECAY + slot2, 0xff); - AL_SendOutputToPort(port, OPL3_SUSTAIN_RELEASE + slot1, 0xff); - AL_SendOutputToPort(port, OPL3_SUSTAIN_RELEASE + slot2, 0xff); - - // Maximum attenuation - AL_SendOutputToPort(port, OPL3_KSL_LEVEL + slot1, 0xff); - AL_SendOutputToPort(port, OPL3_KSL_LEVEL + slot2, 0xff); - } -} - - -static void AL_Reset(void) -{ - AL_SendOutputToPort(ADLIB_PORT, 1, OPL3_ENABLE_WAVE_SELECT); - AL_SendOutputToPort(ADLIB_PORT, OPL3_KBD_SPLIT_REGISTER, 0); - - // Set the values: AM Depth, VIB depth & Rhythm - AL_SendOutputToPort(ADLIB_PORT, OPL3_PERCUSSION_REGISTER, 0); - - AL_SetStereo(AL_Stereo); - - AL_FlushCard(AL_LeftPort); - AL_FlushCard(AL_RightPort); -} - - -void AL_SetStereo(int const stereo) { AL_SendOutputToPort(AL_RightPort, OPL3_MODE_REGISTER, (stereo << 1) + 1); } - - -static void AL_NoteOff(int const channel, int const key, int velocity) -{ - UNREFERENCED_PARAMETER(velocity); - - // We only play channels 1 through 10 - if (channel > AL_MaxMidiChannel) - return; - - int const voice = AL_GetVoice(channel, key); - - if (voice == AL_VoiceNotFound) - return; - - Voice[voice].status = NOTE_OFF; - - int const port = Voice[voice].port; - int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; - - AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, hibyte(Voice[voice].pitchleft)); - - LL_Remove(AdLibVoice, &Channel[channel].Voices, &Voice[voice]); - LL_AddToTail(AdLibVoice, &Voice_Pool, &Voice[voice]); -} - - -static void AL_NoteOn(int const channel, int const key, int const velocity) -{ - // We only play channels 1 through 10 - if (channel > AL_MaxMidiChannel) - return; - - if (velocity == 0) - { - AL_NoteOff(channel, key, velocity); - return; - } - - int voice = AL_AllocVoice(); - - if (voice == AL_VoiceNotFound) - { - if (Channel[9].Voices.start) - { - AL_NoteOff(9, Channel[9].Voices.start->key, 0); - voice = AL_AllocVoice(); - } - - if (voice == AL_VoiceNotFound) - return; - } - - Voice[voice].key = key; - Voice[voice].channel = channel; - Voice[voice].velocity = velocity; - Voice[voice].status = NOTE_ON; - - LL_AddToTail(AdLibVoice, &Channel[channel].Voices, &Voice[voice]); - - AL_SetVoiceTimbre(voice); - AL_SetVoiceVolume(voice); - AL_SetVoicePitch(voice); - AL_SetVoicePan(voice); -} - - -static inline void AL_AllNotesOff(int const channel) -{ - while (Channel[channel].Voices.start != nullptr) - AL_NoteOff(channel, Channel[channel].Voices.start->key, 0); -} - - -static void AL_ControlChange(int const channel, int const type, int const data) -{ - // We only play channels 1 through 10 - if (channel > AL_MaxMidiChannel) - return; - - switch (type) - { - case MIDI_VOLUME: - AL_SetChannelVolume(channel, data); - break; - - case MIDI_PAN: - AL_SetChannelPan(channel, data); - break; - - case MIDI_DETUNE: - AL_SetChannelDetune(channel, data); - break; - - case MIDI_ALL_NOTES_OFF: - AL_AllNotesOff(channel); - break; - - case MIDI_RESET_ALL_CONTROLLERS: - AL_ResetVoices(); - AL_SetChannelVolume(channel, AL_DefaultChannelVolume); - AL_SetChannelPan(channel, 64); - AL_SetChannelDetune(channel, 0); - break; - - case MIDI_RPN_MSB: - Channel[channel].RPN &= 0x00FF; - Channel[channel].RPN |= (data & 0xFF) << 8; - break; - - case MIDI_RPN_LSB: - Channel[channel].RPN &= 0xFF00; - Channel[channel].RPN |= data & 0xFF; - break; - - case MIDI_DATAENTRY_MSB: - if (Channel[channel].RPN == MIDI_PITCHBEND_RPN) - { - Channel[channel].PitchBendSemiTones = data; - Channel[channel].PitchBendRange = Channel[channel].PitchBendSemiTones * 100 + Channel[channel].PitchBendHundreds; - } - break; - - case MIDI_DATAENTRY_LSB: - if (Channel[channel].RPN == MIDI_PITCHBEND_RPN) - { - Channel[channel].PitchBendHundreds = data; - Channel[channel].PitchBendRange = Channel[channel].PitchBendSemiTones * 100 + Channel[channel].PitchBendHundreds; - } - break; - } -} - - -static void AL_ProgramChange(int const channel, int const patch) -{ - // We only play channels 1 through 10 - if (channel > AL_MaxMidiChannel) - return; - - Channel[channel].Timbre = patch; -} - - -static void AL_SetPitchBend(int const channel, int const lsb, int const msb) -{ - // We only play channels 1 through 10 - if (channel > AL_MaxMidiChannel) - return; - - int const pitchbend = lsb + (msb << 8); - int const TotalBend = pitchbend * Channel[channel].PitchBendRange / (PITCHBEND_CENTER / FINETUNE_RANGE); - - Channel[channel].Pitchbend = pitchbend; - Channel[channel].KeyOffset = (int)(TotalBend / FINETUNE_RANGE); - Channel[channel].KeyOffset -= Channel[channel].PitchBendSemiTones; - - Channel[channel].KeyDetune = (uint32_t)(TotalBend % FINETUNE_RANGE); - - auto voice = Channel[channel].Voices.start; - while (voice != nullptr) - { - AL_SetVoicePitch(voice->num); - voice = voice->next; - } -} - - -static void AL_Shutdown(void) -{ - AL_ResetVoices(); - AL_Reset(); -} - - -static int AL_Init(int const rate) -{ - OPL3_Reset(&chip, rate); - - AL_CalcPitchInfo(); - AL_Reset(); - AL_ResetVoices(); - - return AdLibErr_Ok; -} - - -void AL_RegisterTimbreBank(uint8_t const *timbres) -{ - for (int i = 0; i < 256; i++) - { - ADLIB_TimbreBank[i].SAVEK[0] = *(timbres++); - ADLIB_TimbreBank[i].SAVEK[1] = *(timbres++); - ADLIB_TimbreBank[i].Level[0] = *(timbres++); - ADLIB_TimbreBank[i].Level[1] = *(timbres++); - ADLIB_TimbreBank[i].Env1[0] = *(timbres++); - ADLIB_TimbreBank[i].Env1[1] = *(timbres++); - ADLIB_TimbreBank[i].Env2[0] = *(timbres++); - ADLIB_TimbreBank[i].Env2[1] = *(timbres++); - ADLIB_TimbreBank[i].Wave[0] = *(timbres++); - ADLIB_TimbreBank[i].Wave[1] = *(timbres++); - ADLIB_TimbreBank[i].Feedback = *(timbres++); - ADLIB_TimbreBank[i].Transpose = *(int8_t *)(timbres++); - ADLIB_TimbreBank[i].Velocity = *(int8_t *)(timbres++); - } -} diff --git a/source/audiolib/src/driver_adlib.h b/source/audiolib/src/driver_adlib.h deleted file mode 100644 index 198d84ae8..000000000 --- a/source/audiolib/src/driver_adlib.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - -#include "al_midi.h" -#include "midifuncs.h" -#include "opl3.h" - -extern int AL_Stereo; -extern int AL_PostAmp; - -int AdLibDrv_GetError(void); -const char *AdLibDrv_ErrorString(int ErrorNumber); - -int AdLibDrv_MIDI_Init(midifuncs *); -void AdLibDrv_MIDI_Shutdown(void); -int AdLibDrv_MIDI_StartPlayback(void (*service)(void)); -void AdLibDrv_MIDI_HaltPlayback(void); -void AdLibDrv_MIDI_SetTempo(int tempo, int division); - diff --git a/source/audiolib/src/driver_directsound.cpp b/source/audiolib/src/driver_directsound.cpp deleted file mode 100644 index c82891353..000000000 --- a/source/audiolib/src/driver_directsound.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -/** - * DirectSound output driver for MultiVoc - */ - -#define NEED_MMSYSTEM_H -#define NEED_DSOUND_H - -#include "driver_directsound.h" - -#include "compat.h" -#include "multivoc.h" -#include "mutex.h" -#include "windows_inc.h" - -#define MIXBUFFERPOSITIONS 8 - -static int ErrorCode; -static int Initialised; -static int Playing; - -static char * MixBuffer; -static int MixBufferSize; -static int MixBufferCount; -static int MixBufferCurrent; -static int MixBufferUsed; - -static void (*MixCallBack)(void); - -static LPDIRECTSOUND lpds; -static LPDIRECTSOUNDBUFFER lpdsbprimary, lpdsbsec; -static LPDIRECTSOUNDNOTIFY lpdsnotify; - -static HANDLE mixThread; -static mutex_t mutex; - -static DSBPOSITIONNOTIFY notifyPositions[MIXBUFFERPOSITIONS + 1] = {}; - -static void FillBufferPosition(char * ptr, int remaining) -{ - int len = 0; - - do - { - if (MixBufferUsed == MixBufferSize) - { - MixCallBack(); - MixBufferUsed = 0; - - if (++MixBufferCurrent >= MixBufferCount) - MixBufferCurrent -= MixBufferCount; - } - - do - { - char *sptr = MixBuffer + (MixBufferCurrent * MixBufferSize) + MixBufferUsed; - - len = MixBufferSize - MixBufferUsed; - - if (remaining < len) - len = remaining; - - memcpy(ptr, sptr, len); - - ptr += len; - MixBufferUsed += len; - remaining -= len; - } - while (remaining >= len && MixBufferUsed < MixBufferSize); - } - while (remaining >= len); -} - -static void FillBuffer(int bufnum) -{ - LPVOID ptr, ptr2; - DWORD remaining, remaining2; - int retries = 1; - - do - { - HRESULT err = IDirectSoundBuffer_Lock(lpdsbsec, notifyPositions[bufnum].dwOffset, notifyPositions[1].dwOffset, - &ptr, &remaining, &ptr2, &remaining2, 0); - - if (EDUKE32_PREDICT_FALSE(FAILED(err))) - { - if (err == DSERR_BUFFERLOST) - { - if (FAILED(err = IDirectSoundBuffer_Restore(lpdsbsec))) - goto fail; - - if (retries-- > 0) - continue; - } -fail: - MV_Printf("DirectSound FillBuffer: err %x\n", (uint32_t)err); - - return; - } - break; - } - while (1); - - if (ptr && remaining) - FillBufferPosition((char *)ptr, remaining); - - if (ptr2 && remaining2) - FillBufferPosition((char *)ptr2, remaining2); - - IDirectSoundBuffer_Unlock(lpdsbsec, ptr, remaining, ptr2, remaining2); -} - -static DWORD WINAPI fillDataThread(LPVOID lpParameter) -{ - UNREFERENCED_PARAMETER(lpParameter); - - HANDLE handles[MIXBUFFERPOSITIONS+1]; - - for (int i = 0; i < ARRAY_SSIZE(handles); i++) - handles[i] = notifyPositions[i].hEventNotify; - - do - { - DWORD const waitret = WaitForMultipleObjects(MIXBUFFERPOSITIONS, handles, FALSE, INFINITE); - - if (waitret >= WAIT_OBJECT_0 && waitret < WAIT_OBJECT_0+MIXBUFFERPOSITIONS) - { - mutex_lock(&mutex); - FillBuffer((waitret + MIXBUFFERPOSITIONS - 1 - WAIT_OBJECT_0) % MIXBUFFERPOSITIONS); - mutex_unlock(&mutex); - } - else - { - switch (waitret) - { - case WAIT_OBJECT_0 + MIXBUFFERPOSITIONS: - ExitThread(0); - break; - - default: - MV_Printf("DirectSound fillDataThread: wfmo err %d\n", (int)waitret); - break; - } - } - } - while (1); - - return 0; -} - -static void TeardownDSound(HRESULT err) -{ - if (FAILED(err)) - MV_Printf("Dying error: %x\n", (uint32_t)err); - - if (lpdsnotify) - IDirectSoundNotify_Release(lpdsnotify), lpdsnotify = nullptr; - - for (int i = 0; i < MIXBUFFERPOSITIONS + 1; i++) - { - if (notifyPositions[i].hEventNotify) - CloseHandle(notifyPositions[i].hEventNotify); - notifyPositions[i].hEventNotify = 0; - } - -#ifdef RENDERTYPEWIN - if (mutex) - CloseHandle(mutex), mutex = nullptr; -#endif - - if (lpdsbsec) - IDirectSoundBuffer_Release(lpdsbsec), lpdsbsec = nullptr; - - if (lpdsbprimary) - IDirectSoundBuffer_Release(lpdsbprimary), lpdsbprimary = nullptr; - - if (lpds) - IDirectSound_Release(lpds), lpds = nullptr; -} - -static int DirectSound_Error(HRESULT err, int code) -{ - TeardownDSound(err); - ErrorCode = code; - return DSErr_Error; -} - -int DirectSoundDrv_PCM_Init(int *mixrate, int *numchannels, void * initdata) -{ - HRESULT err; - DSBUFFERDESC bufdesc = {}; - WAVEFORMATEX wfex = {}; - - if (Initialised) - DirectSoundDrv_PCM_Shutdown(); - - if (FAILED(err = DirectSoundCreate(0, &lpds, 0))) - return DirectSound_Error(err, DSErr_DirectSoundCreate); - - if (FAILED(err = IDirectSound_SetCooperativeLevel(lpds, (HWND) initdata, DSSCL_PRIORITY))) - return DirectSound_Error(err, DSErr_SetCooperativeLevel); - - bufdesc.dwSize = sizeof(DSBUFFERDESC); - bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; - - if (FAILED(err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbprimary, 0))) - return DirectSound_Error(err, DSErr_CreateSoundBuffer); - - wfex.wFormatTag = WAVE_FORMAT_PCM; - wfex.nChannels = *numchannels; - wfex.nSamplesPerSec = *mixrate; - wfex.wBitsPerSample = 16; - wfex.nBlockAlign = wfex.nChannels * wfex.wBitsPerSample / 8; - wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; - - if (FAILED(err = IDirectSoundBuffer_SetFormat(lpdsbprimary, &wfex))) - return DirectSound_Error(err, DSErr_SetFormat); - - bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; - - bufdesc.dwBufferBytes = wfex.nBlockAlign * 2048 * 2; - bufdesc.lpwfxFormat = &wfex; - - if (FAILED(err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbsec, 0))) - return DirectSound_Error(err, DSErr_CreateSoundBufferSecondary); - - if (FAILED(err = IDirectSoundBuffer_QueryInterface(lpdsbsec, IID_IDirectSoundNotify, (LPVOID *)&lpdsnotify))) - return DirectSound_Error(err, DSErr_Notify); - - for (int i = 0; i < MIXBUFFERPOSITIONS; i++) - { - notifyPositions[i].dwOffset = (bufdesc.dwBufferBytes/MIXBUFFERPOSITIONS)*i; - notifyPositions[i].hEventNotify = CreateEvent(nullptr, FALSE, FALSE, nullptr); - if (!notifyPositions[i].hEventNotify) - return DirectSound_Error(DS_OK, DSErr_NotifyEvents); - } - - notifyPositions[MIXBUFFERPOSITIONS].dwOffset = DSBPN_OFFSETSTOP; - notifyPositions[MIXBUFFERPOSITIONS].hEventNotify = CreateEvent(nullptr, FALSE, FALSE, nullptr); - - if (FAILED(err = IDirectSoundNotify_SetNotificationPositions(lpdsnotify, MIXBUFFERPOSITIONS+1, notifyPositions))) - return DirectSound_Error(err, DSErr_SetNotificationPositions); - - if (FAILED(err = IDirectSoundBuffer_Play(lpdsbprimary, 0, 0, DSBPLAY_LOOPING))) - return DirectSound_Error(err, DSErr_Play); - - Initialised = 1; - - return DSErr_Ok; -} - -void DirectSoundDrv_PCM_Shutdown(void) -{ - if (!Initialised) - return; - - DirectSoundDrv_PCM_StopPlayback(); - TeardownDSound(DS_OK); - - Initialised = 0; -} - -int DirectSoundDrv_PCM_BeginPlayback(char *BufferStart, int BufferSize, int NumDivisions, void (*CallBackFunc)(void)) -{ - if (!Initialised) - { - ErrorCode = DSErr_Uninitialised; - return DSErr_Error; - } - - DirectSoundDrv_PCM_StopPlayback(); - - MixBuffer = BufferStart; - MixBufferSize = BufferSize; - MixBufferCount = NumDivisions; - MixBufferCurrent = 0; - MixBufferUsed = 0; - MixCallBack = CallBackFunc; - - // prime the buffer - FillBuffer(0); - - if ((mixThread = CreateThread(nullptr, 0, fillDataThread, 0, 0, 0)) == nullptr) - { - ErrorCode = DSErr_CreateThread; - return DSErr_Error; - } - - SetThreadPriority(mixThread, THREAD_PRIORITY_ABOVE_NORMAL); - - HRESULT err = IDirectSoundBuffer_Play(lpdsbsec, 0, 0, DSBPLAY_LOOPING); - - if (FAILED(err)) - { - ErrorCode = DSErr_PlaySecondary; - return DSErr_Error; - } - - Playing = 1; - - return DSErr_Ok; -} - -void DirectSoundDrv_PCM_StopPlayback(void) -{ - if (!Playing) - return; - - IDirectSoundBuffer_Stop(lpdsbsec); - IDirectSoundBuffer_SetCurrentPosition(lpdsbsec, 0); - - Playing = 0; -} - -void DirectSoundDrv_PCM_Lock(void) -{ - mutex_lock(&mutex); -} - -void DirectSoundDrv_PCM_Unlock(void) -{ - mutex_unlock(&mutex); -} - -int DirectSoundDrv_GetError(void) -{ - return ErrorCode; -} - -const char *DirectSoundDrv_ErrorString(int ErrorNumber) -{ - const char *ErrorString; - - switch (ErrorNumber) - { - case DSErr_Warning: - case DSErr_Error: - ErrorString = DirectSoundDrv_ErrorString(ErrorCode); - break; - - case DSErr_Ok: - ErrorString = "DirectSound ok."; - break; - - case DSErr_Uninitialised: - ErrorString = "DirectSound uninitialised."; - break; - - case DSErr_DirectSoundCreate: - ErrorString = "DirectSound error: DirectSoundCreate failed."; - break; - - case DSErr_SetCooperativeLevel: - ErrorString = "DirectSound error: SetCooperativeLevel failed."; - break; - - case DSErr_CreateSoundBuffer: - ErrorString = "DirectSound error: primary CreateSoundBuffer failed."; - break; - - case DSErr_CreateSoundBufferSecondary: - ErrorString = "DirectSound error: secondary CreateSoundBuffer failed."; - break; - - case DSErr_SetFormat: - ErrorString = "DirectSound error: primary buffer SetFormat failed."; - break; - - case DSErr_SetFormatSecondary: - ErrorString = "DirectSound error: secondary buffer SetFormat failed."; - break; - - case DSErr_Notify: - ErrorString = "DirectSound error: failed querying secondary buffer for notify interface."; - break; - - case DSErr_NotifyEvents: - ErrorString = "DirectSound error: failed creating notify events."; - break; - - case DSErr_SetNotificationPositions: - ErrorString = "DirectSound error: failed setting notification positions."; - break; - - case DSErr_Play: - ErrorString = "DirectSound error: primary buffer Play failed."; - break; - - case DSErr_PlaySecondary: - ErrorString = "DirectSound error: secondary buffer Play failed."; - break; - - case DSErr_CreateThread: - ErrorString = "DirectSound error: failed creating mix thread."; - break; - - default: - ErrorString = "Unknown DirectSound error code."; - break; - } - - return ErrorString; -} diff --git a/source/audiolib/src/driver_directsound.h b/source/audiolib/src/driver_directsound.h deleted file mode 100644 index 68874707d..000000000 --- a/source/audiolib/src/driver_directsound.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -#include - -enum -{ - DSErr_Warning = -2, - DSErr_Error = -1, - DSErr_Ok = 0, - DSErr_Uninitialised, - DSErr_DirectSoundCreate, - DSErr_SetCooperativeLevel, - DSErr_CreateSoundBuffer, - DSErr_CreateSoundBufferSecondary, - DSErr_SetFormat, - DSErr_SetFormatSecondary, - DSErr_Notify, - DSErr_NotifyEvents, - DSErr_SetNotificationPositions, - DSErr_Play, - DSErr_PlaySecondary, - DSErr_CreateThread, -}; - -int DirectSoundDrv_GetError(void); -const char *DirectSoundDrv_ErrorString(int ErrorNumber); - -int DirectSoundDrv_PCM_Init(int *mixrate, int *numchannels, void *initdata); -void DirectSoundDrv_PCM_Shutdown(void); -int DirectSoundDrv_PCM_BeginPlayback(char *BufferStart, int BufferSize, int NumDivisions, void (*CallBackFunc)(void)); -void DirectSoundDrv_PCM_StopPlayback(void); -void DirectSoundDrv_PCM_Lock(void); -void DirectSoundDrv_PCM_Unlock(void); diff --git a/source/audiolib/src/driver_sdl.cpp b/source/audiolib/src/driver_sdl.cpp deleted file mode 100644 index 9e8b9d5b3..000000000 --- a/source/audiolib/src/driver_sdl.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -/** - * libSDL output driver for MultiVoc - */ - -#include "driver_sdl.h" - -#include "compat.h" -#include "multivoc.h" -#include "mutex.h" -#include "sdl_inc.h" - -enum { - SDLErr_Warning = -2, - SDLErr_Error = -1, - SDLErr_Ok = 0, - SDLErr_Uninitialised, - SDLErr_InitSubSystem, - SDLErr_OpenAudio -}; - -static int ErrorCode = SDLErr_Ok; -static int Initialised; -static int Playing; -static uint32_t StartedSDL; - -static char *MixBuffer; -static int MixBufferSize; -static int MixBufferCount; -static int MixBufferCurrent; -static int MixBufferUsed; -static void (*MixCallBack)(void); - -#if (SDL_MAJOR_VERSION == 2) -static SDL_AudioDeviceID audio_dev; -#endif - -static void fillData(void * userdata, Uint8 * ptr, int remaining) -{ - if (!MixBuffer || !MixCallBack) - return; - - UNREFERENCED_PARAMETER(userdata); - - int len; - char *sptr; - - while (remaining > 0) { - if (MixBufferUsed == MixBufferSize) { - MixCallBack(); - - MixBufferUsed = 0; - MixBufferCurrent++; - if (MixBufferCurrent >= MixBufferCount) { - MixBufferCurrent -= MixBufferCount; - } - } - - while (remaining > 0 && MixBufferUsed < MixBufferSize) { - sptr = MixBuffer + (MixBufferCurrent * MixBufferSize) + MixBufferUsed; - - len = MixBufferSize - MixBufferUsed; - if (remaining < len) { - len = remaining; - } - - memcpy(ptr, sptr, len); - - ptr += len; - MixBufferUsed += len; - remaining -= len; - } - } -} - -int SDLDrv_GetError(void) -{ - return ErrorCode; -} - -const char *SDLDrv_ErrorString(int ErrorNumber) -{ - const char *ErrorString; - - switch( ErrorNumber ) { - case SDLErr_Warning : - case SDLErr_Error : - ErrorString = SDLDrv_ErrorString( ErrorCode ); - break; - - case SDLErr_Ok : - ErrorString = "SDL Audio ok."; - break; - - case SDLErr_Uninitialised: - ErrorString = "SDL Audio uninitialised."; - break; - - case SDLErr_InitSubSystem: - ErrorString = "SDL Audio: error in Init or InitSubSystem."; - break; - - case SDLErr_OpenAudio: - ErrorString = "SDL Audio: error in OpenAudio."; - break; - - default: - ErrorString = "Unknown SDL Audio error code."; - break; - } - - return ErrorString; -} - -int SDLDrv_PCM_Init(int *mixrate, int *numchannels, void * initdata) -{ - UNREFERENCED_PARAMETER(initdata); - - Uint32 inited; - int err = 0; - SDL_AudioSpec spec, actual; - - if (Initialised) { - SDLDrv_PCM_Shutdown(); - } - - inited = SDL_WasInit(SDL_INIT_AUDIO); - - if (!(inited & SDL_INIT_AUDIO)) { - err = SDL_InitSubSystem(SDL_INIT_AUDIO); - StartedSDL = SDL_WasInit(SDL_INIT_AUDIO); - } - - if (err < 0) { - ErrorCode = SDLErr_InitSubSystem; - return SDLErr_Error; - } - - int chunksize = 512; -#ifdef __ANDROID__ - chunksize = droidinfo.audio_buffer_size; -#endif - - spec.freq = *mixrate; - spec.format = AUDIO_S16SYS; - spec.channels = *numchannels; - spec.samples = chunksize; - spec.callback = fillData; - spec.userdata = nullptr; - - Bmemset(&actual, 0, sizeof(actual)); - -#if (SDL_MAJOR_VERSION == 1) - err = !SDL_OpenAudio(&spec, &actual); -#else - audio_dev = err = SDL_OpenAudioDevice(nullptr, 0, &spec, &actual, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); -#endif - - if (err == 0) { - ErrorCode = SDLErr_OpenAudio; - return SDLErr_Error; - } - -#if (SDL_MAJOR_VERSION == 1) - char drivername[64] = "(error)"; - SDL_AudioDriverName(drivername, sizeof(drivername)); - MV_Printf("SDL %s driver\n", drivername); -#else - auto drivername = Xstrdup(SDL_GetCurrentAudioDriver()); - - for (int i=0;drivername[i] != 0;++i) - drivername[i] = toupper(drivername[i]); - - auto devname = Xstrdup(SDL_GetAudioDeviceName(0, 0)); - auto pdevname = Bstrchr(devname, '('); - - if (pdevname) - { - auto rt = Bstrchr(pdevname++, ')'); - if (rt != nullptr) *rt = '\0'; - } - else - pdevname = devname; - - MV_Printf("SDL %s driver on %s\n", drivername, pdevname); - - Xfree(devname); - Xfree(drivername); -#endif - -#if (SDL_MAJOR_VERSION == 1) - if (actual.freq == 0 || actual.channels == 0) { - // hack for when SDL said it opened the audio, but clearly didn't - SDL_CloseAudio(); - ErrorCode = SDLErr_OpenAudio; - return SDLErr_Error; - } -#endif - err = 0; - - *mixrate = actual.freq; - if (actual.format == AUDIO_U8 || actual.format == AUDIO_S8) - { - ErrorCode = SDLErr_OpenAudio; - err = 1; - } - - *numchannels = actual.channels; - if (actual.channels != 1 && actual.channels != 2) - { - ErrorCode = SDLErr_OpenAudio; - err = 1; - } - - if (err) - { - SDL_CloseAudio(); - return SDLErr_Error; - } - - Initialised = 1; - return SDLErr_Ok; -} - -void SDLDrv_PCM_Shutdown(void) -{ - if (!Initialised) - return; - - if (StartedSDL) - SDL_QuitSubSystem(StartedSDL); - - StartedSDL = 0; - Initialised = 0; -} - -int SDLDrv_PCM_BeginPlayback(char *BufferStart, int BufferSize, - int NumDivisions, void ( *CallBackFunc )( void ) ) -{ - if (!Initialised) { - ErrorCode = SDLErr_Uninitialised; - return SDLErr_Error; - } - - if (Playing) { - SDLDrv_PCM_StopPlayback(); - } - - MixBuffer = BufferStart; - MixBufferSize = BufferSize; - MixBufferCount = NumDivisions; - MixBufferCurrent = 0; - MixBufferUsed = 0; - MixCallBack = CallBackFunc; - - // prime the buffer - MixCallBack(); - -#if (SDL_MAJOR_VERSION == 2) - SDL_PauseAudioDevice(audio_dev, 0); -#else - SDL_PauseAudio(0); -#endif - Playing = 1; - - return SDLErr_Ok; -} - -void SDLDrv_PCM_StopPlayback(void) -{ - if (!Initialised || !Playing) { - return; - } - -#if (SDL_MAJOR_VERSION == 2) - SDL_PauseAudioDevice(audio_dev, 1); -#else - SDL_PauseAudio(1); -#endif - - Playing = 0; -} - -void SDLDrv_PCM_Lock(void) -{ -#if (SDL_MAJOR_VERSION == 2) - SDL_LockAudioDevice(audio_dev); -#else - SDL_LockAudio(); -#endif -} - -void SDLDrv_PCM_Unlock(void) -{ -#if (SDL_MAJOR_VERSION == 2) - SDL_UnlockAudioDevice(audio_dev); -#else - SDL_UnlockAudio(); -#endif -} diff --git a/source/audiolib/src/driver_sdl.h b/source/audiolib/src/driver_sdl.h deleted file mode 100644 index f3737a87b..000000000 --- a/source/audiolib/src/driver_sdl.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -#ifndef driver_sdl_h__ -#define driver_sdl_h__ - -#include "compat.h" - -int SDLDrv_GetError(void); -const char *SDLDrv_ErrorString( int ErrorNumber ); -int SDLDrv_PCM_Init(int *mixrate, int *numchannels, void * initdata); -void SDLDrv_PCM_Shutdown(void); -int SDLDrv_PCM_BeginPlayback(char *BufferStart, int BufferSize, - int NumDivisions, void ( *CallBackFunc )( void ) ); -void SDLDrv_PCM_StopPlayback(void); -void SDLDrv_PCM_Lock(void); -void SDLDrv_PCM_Unlock(void); -#endif // driver_sdl_h__ diff --git a/source/audiolib/src/driver_winmm.cpp b/source/audiolib/src/driver_winmm.cpp deleted file mode 100644 index 87a93b948..000000000 --- a/source/audiolib/src/driver_winmm.cpp +++ /dev/null @@ -1,838 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - -/** - * WinMM MIDI output driver - */ - -#include "driver_winmm.h" - -#include "compat.h" -#include "ll.h" -#include "midifuncs.h" -#include "multivoc.h" - -#include - -#ifdef _MSC_VER -#define inline _inline -#endif - -enum -{ - WinMMErr_Warning = -2, - WinMMErr_Error = -1, - WinMMErr_Ok = 0, - WinMMErr_Uninitialised, - WinMMErr_NotifyWindow, - WinMMErr_MIDIStreamOpen, - WinMMErr_MIDIStreamRestart, - WinMMErr_MIDICreateEvent, - WinMMErr_MIDIPlayThread, - WinMMErr_MIDICreateMutex -}; - -static int ErrorCode = WinMMErr_Ok; - -static BOOL midiInstalled; -static HMIDISTRM midiStream; -static UINT midiDeviceID = MIDI_MAPPER; -static void (*midiThreadService)(void); -static uint32_t midiThreadTimer; -static uint32_t midiLastEventTime; -static uint32_t midiThreadQueueTimer; -static uint32_t midiThreadQueueTicks; -static HANDLE midiThread; -static HANDLE midiThreadQuitEvent; -static HANDLE midiMutex; -static BOOL midiStreamRunning; -static int midiLastDivision; -#define THREAD_QUEUE_INTERVAL 10 // 1/10 sec -#define MIDI_BUFFER_SPACE (12*128u) // 128 note-on events - -typedef struct MidiBuffer { - struct MidiBuffer *next; - struct MidiBuffer *prev; - - BOOL prepared; - MIDIHDR hdr; -} MidiBuffer; - -static volatile MidiBuffer activeMidiBuffers; -static volatile MidiBuffer spareMidiBuffers; -static MidiBuffer *currentMidiBuffer; - -#define MIDI_NOTE_OFF 0x80 -#define MIDI_NOTE_ON 0x90 -#define MIDI_POLY_AFTER_TCH 0xA0 -#define MIDI_CONTROL_CHANGE 0xB0 -#define MIDI_PROGRAM_CHANGE 0xC0 -#define MIDI_AFTER_TOUCH 0xD0 -#define MIDI_PITCH_BEND 0xE0 -#define MIDI_META_EVENT 0xFF -#define MIDI_END_OF_TRACK 0x2F -#define MIDI_TEMPO_CHANGE 0x51 -#define MIDI_MONO_MODE_ON 0x7E -#define MIDI_ALL_NOTES_OFF 0x7B - - -int WinMMDrv_GetError(void) -{ - return ErrorCode; -} - -const char *WinMMDrv_ErrorString( int ErrorNumber ) -{ - const char *ErrorString; - - switch( ErrorNumber ) - { - case WinMMErr_Warning : - case WinMMErr_Error : - ErrorString = WinMMDrv_ErrorString( ErrorCode ); - break; - - case WinMMErr_Ok : - ErrorString = "WinMM ok."; - break; - - case WinMMErr_Uninitialised: - ErrorString = "WinMM uninitialised."; - break; - - case WinMMErr_MIDIStreamOpen: - ErrorString = "MIDI error: failed opening stream."; - break; - - case WinMMErr_MIDIStreamRestart: - ErrorString = "MIDI error: failed starting stream."; - break; - - case WinMMErr_MIDICreateEvent: - ErrorString = "MIDI error: failed creating play thread quit event."; - break; - - case WinMMErr_MIDIPlayThread: - ErrorString = "MIDI error: failed creating play thread."; - break; - - case WinMMErr_MIDICreateMutex: - ErrorString = "MIDI error: failed creating play mutex."; - break; - - default: - ErrorString = "Unknown WinMM error code."; - break; - } - - return ErrorString; - -} - - -// will append "err nnn (ssss)\n" to the end of the string it emits -static void midi_error(MMRESULT rv, const char * fmt, ...) -{ - va_list va; - const char * errtxt = "?"; - - switch (rv) { - case MMSYSERR_NOERROR: errtxt = "MMSYSERR_NOERROR"; break; - case MMSYSERR_BADDEVICEID: errtxt = "MMSYSERR_BADDEVICEID"; break; - case MMSYSERR_NOTENABLED: errtxt = "MMSYSERR_NOTENABLED"; break; - case MMSYSERR_ALLOCATED: errtxt = "MMSYSERR_ALLOCATED"; break; - case MMSYSERR_INVALHANDLE: errtxt = "MMSYSERR_INVALHANDLE"; break; - case MMSYSERR_NODRIVER: errtxt = "MMSYSERR_NODRIVER"; break; - case MMSYSERR_NOMEM: errtxt = "MMSYSERR_NOMEM"; break; - case MMSYSERR_NOTSUPPORTED: errtxt = "MMSYSERR_NOTSUPPORTED"; break; - case MMSYSERR_BADERRNUM: errtxt = "MMSYSERR_BADERRNUM"; break; - case MMSYSERR_INVALFLAG: errtxt = "MMSYSERR_INVALFLAG"; break; - case MMSYSERR_INVALPARAM: errtxt = "MMSYSERR_INVALPARAM"; break; - case MMSYSERR_HANDLEBUSY: errtxt = "MMSYSERR_HANDLEBUSY"; break; - case MMSYSERR_INVALIDALIAS: errtxt = "MMSYSERR_INVALIDALIAS"; break; - case MMSYSERR_BADDB: errtxt = "MMSYSERR_BADDB"; break; - case MMSYSERR_KEYNOTFOUND: errtxt = "MMSYSERR_KEYNOTFOUND"; break; - case MMSYSERR_READERROR: errtxt = "MMSYSERR_READERROR"; break; - case MMSYSERR_WRITEERROR: errtxt = "MMSYSERR_WRITEERROR"; break; - case MMSYSERR_DELETEERROR: errtxt = "MMSYSERR_DELETEERROR"; break; - case MMSYSERR_VALNOTFOUND: errtxt = "MMSYSERR_VALNOTFOUND"; break; - case MMSYSERR_NODRIVERCB: errtxt = "MMSYSERR_NODRIVERCB"; break; - default: break; - } - - va_start(va, fmt); - MV_Printf(fmt, va); - va_end(va); - - MV_Printf(" err %d (%s)\n", (int)rv, errtxt); -} - -static void midi_dispose_buffer(MidiBuffer * node, const char * caller) -{ - MMRESULT rv; - - if (node->prepared) { - rv = midiOutUnprepareHeader( (HMIDIOUT) midiStream, &node->hdr, sizeof(MIDIHDR) ); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "WinMM %s/midi_dispose_buffer midiOutUnprepareHeader", caller); - } - node->prepared = FALSE; - } - - if (midiThread) { - // remove the node from the activeMidiBuffers list - LL_Remove( node, next, prev ); - - // when playing, we keep the buffers - LL_Add( (MidiBuffer*) &spareMidiBuffers, node, next, prev ); - //MV_Printf("WinMM %s/midi_dispose_buffer recycling buffer %p\n", caller, node); - } else { - // when not, we throw them away - free(node); - //MV_Printf("WinMM %s/midi_dispose_buffer freeing buffer %p\n", caller, node); - } -} - -static void midi_gc_buffers(void) -{ - MidiBuffer *node, *next; - - for ( node = activeMidiBuffers.next; node != &activeMidiBuffers; node = next ) { - next = node->next; - - if (node->hdr.dwFlags & MHDR_DONE) { - midi_dispose_buffer(node, "midi_gc_buffers"); - } - } -} - -static void midi_free_buffers(void) -{ - MidiBuffer *node, *next; - - //MV_Printf("waiting for active buffers to return\n"); - while (!LL_ListEmpty(&activeMidiBuffers, next, prev)) { - // wait for Windows to finish with all the buffers queued - midi_gc_buffers(); - //MV_Printf("waiting...\n"); - Sleep(10); - } - //MV_Printf("waiting over\n"); - - for ( node = spareMidiBuffers.next; node != &spareMidiBuffers; node = next ) { - next = node->next; - LL_Remove( node, next, prev ); - free(node); - //MV_Printf("WinMM midi_free_buffers freeing buffer %p\n", node); - } - - assert(currentMidiBuffer == 0); -} - -static void midi_flush_current_buffer(void) -{ - MMRESULT rv; - MIDIEVENT * evt; - BOOL needsPrepare = FALSE; - - if (!currentMidiBuffer) { - return; - } - - evt = (MIDIEVENT *) currentMidiBuffer->hdr.lpData; - - if (!midiThread) { - // immediate messages don't use a MIDIEVENT header so strip it off and - // make some adjustments - - currentMidiBuffer->hdr.dwBufferLength = currentMidiBuffer->hdr.dwBytesRecorded - 12; - currentMidiBuffer->hdr.dwBytesRecorded = 0; - currentMidiBuffer->hdr.lpData = (LPSTR) &evt->dwParms[0]; - - if (currentMidiBuffer->hdr.dwBufferLength > 0) { - needsPrepare = TRUE; - } - } else { - needsPrepare = TRUE; - } - - if (needsPrepare) { - // playing a file, or sending a sysex when not playing means - // we need to prepare the buffer - rv = midiOutPrepareHeader( (HMIDIOUT) midiStream, ¤tMidiBuffer->hdr, sizeof(MIDIHDR) ); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "WinMM midi_flush_current_buffer midiOutPrepareHeader"); - return; - } - - currentMidiBuffer->prepared = TRUE; - } - - if (midiThread) { - // midi file playing, so send events to the stream - - LL_Add( (MidiBuffer*) &activeMidiBuffers, currentMidiBuffer, next, prev ); - - rv = midiStreamOut(midiStream, ¤tMidiBuffer->hdr, sizeof(MIDIHDR)); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "WinMM midi_flush_current_buffer midiStreamOut"); - midi_dispose_buffer(currentMidiBuffer, "midi_flush_current_buffer"); - return; - } - - //MV_Printf("WinMM midi_flush_current_buffer queued buffer %p\n", currentMidiBuffer); - } else { - // midi file not playing, so send immediately - - if (currentMidiBuffer->hdr.dwBufferLength > 0) { - rv = midiOutLongMsg( (HMIDIOUT) midiStream, ¤tMidiBuffer->hdr, sizeof(MIDIHDR) ); - if (rv == MMSYSERR_NOERROR) { - // busy-wait for Windows to be done with it - while (!(currentMidiBuffer->hdr.dwFlags & MHDR_DONE)) ; - - //MV_Printf("WinMM midi_flush_current_buffer sent immediate long\n"); - } else { - midi_error(rv, "WinMM midi_flush_current_buffer midiOutLongMsg"); - } - } else { - rv = midiOutShortMsg( (HMIDIOUT) midiStream, evt->dwEvent ); - if (rv == MMSYSERR_NOERROR) { - //MV_Printf("WinMM midi_flush_current_buffer sent immediate short\n"); - } else { - midi_error(rv, "WinMM midi_flush_current_buffer midiOutShortMsg"); - } - } - - midi_dispose_buffer(currentMidiBuffer, "midi_flush_current_buffer"); - } - - currentMidiBuffer = 0; -} - -static void midi_setup_event(int length, unsigned char ** data) -{ - MIDIEVENT * evt; - - evt = (MIDIEVENT *) ((intptr_t) currentMidiBuffer->hdr.lpData + - currentMidiBuffer->hdr.dwBytesRecorded); - - evt->dwDeltaTime = midiThread ? (midiThreadTimer - midiLastEventTime) : 0; - evt->dwStreamID = 0; - - if (length <= 3) { - evt->dwEvent = (DWORD)MEVT_SHORTMSG << 24; - *data = (unsigned char *) &evt->dwEvent; - } else { - evt->dwEvent = ((DWORD)MEVT_LONGMSG << 24) | (length & 0x00ffffff); - *data = (unsigned char *) &evt->dwParms[0]; - } -} - -/* Gets space in the buffer presently being filled. - If insufficient space can be found in the buffer, - what is there is flushed to the stream and a new - buffer large enough is allocated. - - Returns a pointer to starting writing at in 'data'. - */ -static BOOL midi_get_buffer(int length, unsigned char ** data) -{ - uint32_t datalen; - MidiBuffer * node; - - // determine the space to alloc. - // the size of a MIDIEVENT is 3*sizeof(DWORD) = 12. - // short messages need only that amount of space. - // long messages need additional space equal to the length of - // the message, padded to 4 bytes - - if (length <= 3) { - datalen = 12; - } else { - datalen = 12 + length; - if ((datalen & 3) > 0) { - datalen += 4 - (datalen & 3); - } - } - - if (!midiThread) { - assert(currentMidiBuffer == 0); - } - - if (currentMidiBuffer && (currentMidiBuffer->hdr.dwBufferLength - - currentMidiBuffer->hdr.dwBytesRecorded) >= datalen) { - // there was enough space in the current buffer, so hand that back - midi_setup_event(length, data); - - currentMidiBuffer->hdr.dwBytesRecorded += datalen; - - return TRUE; - } - - if (currentMidiBuffer) { - // not enough space in the current buffer to accommodate the - // new data, so flush it to the stream - midi_flush_current_buffer(); - currentMidiBuffer = 0; - } - - // check if there's a spare buffer big enough to hold the message - if (midiThread) { - for ( node = spareMidiBuffers.next; node != &spareMidiBuffers; node = node->next ) { - if (node->hdr.dwBufferLength >= datalen) { - // yes! - LL_Remove( node, next, prev ); - - node->hdr.dwBytesRecorded = 0; - memset(node->hdr.lpData, 0, node->hdr.dwBufferLength); - - currentMidiBuffer = node; - - //MV_Printf("WinMM midi_get_buffer fetched buffer %p\n", node); - break; - } - } - } - - if (!currentMidiBuffer) { - // there were no spare buffers, or none were big enough, so - // allocate a new one - int size; - - if (midiThread) { - // playing a file, so allocate a buffer for more than - // one event - size = max(MIDI_BUFFER_SPACE, datalen); - } else { - // not playing a file, so allocate just a buffer for - // the event we'll be sending immediately - size = datalen; - } - - node = (MidiBuffer *) malloc( sizeof(MidiBuffer) + size ); - if (node == 0) { - return FALSE; - } - - memset(node, 0, sizeof(MidiBuffer) + datalen); - node->hdr.dwUser = (DWORD_PTR) node; - node->hdr.lpData = (LPSTR) ((intptr_t)node + sizeof(MidiBuffer)); - node->hdr.dwBufferLength = size; - node->hdr.dwBytesRecorded = 0; - - currentMidiBuffer = node; - - //MV_Printf("WinMM midi_get_buffer allocated buffer %p\n", node); - } - - midi_setup_event(length, data); - - currentMidiBuffer->hdr.dwBytesRecorded += datalen; - - return TRUE; -} - -static inline void midi_sequence_event(void) -{ - if (!midiThread) { - // a midi event being sent out of playback (streaming) mode - midi_flush_current_buffer(); - return; - } - - //MV_Printf("WinMM midi_sequence_event buffered\n"); - - // update the delta time counter - midiLastEventTime = midiThreadTimer; -} - -static void Func_NoteOff( int channel, int key, int velocity ) -{ - unsigned char * data; - - if (midi_get_buffer(3, &data)) { - data[0] = MIDI_NOTE_OFF | channel; - data[1] = key; - data[2] = velocity; - midi_sequence_event(); - } else MV_Printf("WinMM Func_NoteOff error\n"); -} - -static void Func_NoteOn( int channel, int key, int velocity ) -{ - unsigned char * data; - - if (midi_get_buffer(3, &data)) { - data[0] = MIDI_NOTE_ON | channel; - data[1] = key; - data[2] = velocity; - midi_sequence_event(); - } else MV_Printf("WinMM Func_NoteOn error\n"); -} - -static void Func_PolyAftertouch( int channel, int key, int pressure ) -{ - unsigned char * data; - - if (midi_get_buffer(3, &data)) { - data[0] = MIDI_POLY_AFTER_TCH | channel; - data[1] = key; - data[2] = pressure; - midi_sequence_event(); - } else MV_Printf("WinMM Func_PolyAftertouch error\n"); -} - -static void Func_ControlChange( int channel, int number, int value ) -{ - unsigned char * data; - - if (midi_get_buffer(3, &data)) { - data[0] = MIDI_CONTROL_CHANGE | channel; - data[1] = number; - data[2] = value; - midi_sequence_event(); - } else MV_Printf("WinMM Func_ControlChange error\n"); -} - -static void Func_ProgramChange( int channel, int program ) -{ - unsigned char * data; - - if (midi_get_buffer(2, &data)) { - data[0] = MIDI_PROGRAM_CHANGE | channel; - data[1] = program; - midi_sequence_event(); - } else MV_Printf("WinMM Func_ProgramChange error\n"); -} - -static void Func_ChannelAftertouch( int channel, int pressure ) -{ - unsigned char * data; - - if (midi_get_buffer(2, &data)) { - data[0] = MIDI_AFTER_TOUCH | channel; - data[1] = pressure; - midi_sequence_event(); - } else MV_Printf("WinMM Func_ChannelAftertouch error\n"); -} - -static void Func_PitchBend( int channel, int lsb, int msb ) -{ - unsigned char * data; - - if (midi_get_buffer(3, &data)) { - data[0] = MIDI_PITCH_BEND | channel; - data[1] = lsb; - data[2] = msb; - midi_sequence_event(); - } else MV_Printf("WinMM Func_PitchBend error\n"); -} - -static void Func_SysEx( const unsigned char * data, int length ) -{ - unsigned char * wdata; - - if (midi_get_buffer(length, &wdata)) { - memcpy(wdata, data, length); - midi_sequence_event(); - } else MV_Printf("WinMM Func_SysEx error\n"); -} - -int WinMMDrv_MIDI_Init(midifuncs * funcs) -{ - MMRESULT rv; - - if (midiInstalled) { - WinMMDrv_MIDI_Shutdown(); - } - - memset(funcs, 0, sizeof(midifuncs)); - - LL_Reset( (MidiBuffer*) &activeMidiBuffers, next, prev ); - LL_Reset( (MidiBuffer*) &spareMidiBuffers, next, prev ); - - midiMutex = CreateMutex(0, FALSE, 0); - if (!midiMutex) { - ErrorCode = WinMMErr_MIDICreateMutex; - return WinMMErr_Error; - } - - rv = midiStreamOpen(&midiStream, &midiDeviceID, 1, (DWORD_PTR) 0, (DWORD_PTR) 0, CALLBACK_NULL); - if (rv != MMSYSERR_NOERROR) { - CloseHandle(midiMutex); - midiMutex = 0; - - midi_error(rv, "WinMM MIDI_Init midiStreamOpen"); - ErrorCode = WinMMErr_MIDIStreamOpen; - return WinMMErr_Error; - } - - funcs->NoteOff = Func_NoteOff; - funcs->NoteOn = Func_NoteOn; - funcs->PolyAftertouch = Func_PolyAftertouch; - funcs->ControlChange = Func_ControlChange; - funcs->ProgramChange = Func_ProgramChange; - funcs->ChannelAftertouch = Func_ChannelAftertouch; - funcs->PitchBend = Func_PitchBend; - funcs->SysEx = Func_SysEx; - - midiInstalled = TRUE; - - return WinMMErr_Ok; -} - -void WinMMDrv_MIDI_Shutdown(void) -{ - MMRESULT rv; - - if (!midiInstalled) { - return; - } - - WinMMDrv_MIDI_HaltPlayback(); - - if (midiStream) { - rv = midiStreamClose(midiStream); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "WinMM MIDI_Shutdown midiStreamClose"); - } - } - - if (midiMutex) { - CloseHandle(midiMutex); - } - - midiStream = 0; - midiMutex = 0; - - midiInstalled = FALSE; -} - -static DWORD midi_get_tick(void) -{ - MMRESULT rv; - MMTIME mmtime; - - mmtime.wType = TIME_TICKS; - - rv = midiStreamPosition(midiStream, &mmtime, sizeof(MMTIME)); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "WinMM midi_get_tick midiStreamPosition"); - return 0; - } - - return mmtime.u.ticks; -} - -static DWORD WINAPI midiDataThread(LPVOID lpParameter) -{ - UNREFERENCED_PARAMETER(lpParameter); - - DWORD waitret; - DWORD sequenceTime; - DWORD sleepAmount = 100 / THREAD_QUEUE_INTERVAL; - - // MV_Printf("WinMM midiDataThread: started\n"); - - midiThreadTimer = midi_get_tick(); - midiLastEventTime = midiThreadTimer; - midiThreadQueueTimer = midiThreadTimer + midiThreadQueueTicks; - - WinMMDrv_MIDI_Lock(); - midi_gc_buffers(); - while (midiThreadTimer < midiThreadQueueTimer) { - if (midiThreadService) { - midiThreadService(); - } - midiThreadTimer++; - } - midi_flush_current_buffer(); - WinMMDrv_MIDI_Unlock(); - - do { - waitret = WaitForSingleObject(midiThreadQuitEvent, sleepAmount); - if (waitret == WAIT_OBJECT_0) { - // MV_Printf("WinMM midiDataThread: exiting\n"); - break; - } else if (waitret == WAIT_TIMEOUT) { - // queue a tick - sequenceTime = midi_get_tick(); - - sleepAmount = 100 / THREAD_QUEUE_INTERVAL; - if ((midiThreadTimer - sequenceTime) > midiThreadQueueTicks) { - // we're running ahead, so sleep for half the usual - // amount and try again - sleepAmount /= 2; - continue; - } - - midiThreadQueueTimer = sequenceTime + midiThreadQueueTicks; - - WinMMDrv_MIDI_Lock(); - midi_gc_buffers(); - while (midiThreadTimer < midiThreadQueueTimer) { - if (midiThreadService) { - midiThreadService(); - } - midiThreadTimer++; - } - midi_flush_current_buffer(); - WinMMDrv_MIDI_Unlock(); - - } else { - MV_Printf("WinMM midiDataThread: wfmo err %d\n", (int) waitret); - } - } while (1); - - return 0; -} - -int WinMMDrv_MIDI_StartPlayback(void (*service)(void)) -{ - MMRESULT rv; - - WinMMDrv_MIDI_HaltPlayback(); - - midiThreadService = service; - - midiThreadQuitEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); - if (!midiThreadQuitEvent) { - ErrorCode = WinMMErr_MIDICreateEvent; - return WinMMErr_Error; - } - - if (!midiStreamRunning) { - rv = midiStreamRestart(midiStream); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "MIDI_StartPlayback midiStreamRestart"); - WinMMDrv_MIDI_HaltPlayback(); - ErrorCode = WinMMErr_MIDIStreamRestart; - return WinMMErr_Error; - } - - midiStreamRunning = TRUE; - } - - midiThread = CreateThread(nullptr, 0, midiDataThread, 0, 0, 0); - if (!midiThread) { - WinMMDrv_MIDI_HaltPlayback(); - ErrorCode = WinMMErr_MIDIPlayThread; - return WinMMErr_Error; - } - - midiLastDivision = 0; - - return WinMMErr_Ok; -} - -void WinMMDrv_MIDI_HaltPlayback(void) -{ - MMRESULT rv; - - if (midiThread) { - SetEvent(midiThreadQuitEvent); - - WaitForSingleObject(midiThread, INFINITE); - // MV_Printf("WinMM MIDI_HaltPlayback synched\n"); - - CloseHandle(midiThread); - } - - if (midiThreadQuitEvent) { - CloseHandle(midiThreadQuitEvent); - } - - if (midiStreamRunning) { - // MV_Printf("stopping stream\n"); - rv = midiStreamStop(midiStream); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "WinMM MIDI_HaltPlayback midiStreamStop"); - } - // MV_Printf("stream stopped\n"); - - midiStreamRunning = FALSE; - } - - midi_free_buffers(); - - midiThread = 0; - midiThreadQuitEvent = 0; -} - -void WinMMDrv_MIDI_SetTempo(int tempo, int division) -{ - MMRESULT rv; - MIDIPROPTEMPO propTempo; - MIDIPROPTIMEDIV propTimediv; - BOOL running = midiStreamRunning; - - //MV_Printf("MIDI_SetTempo %d/%d\n", tempo, division); - - propTempo.cbStruct = sizeof(MIDIPROPTEMPO); - propTempo.dwTempo = 60000000l / tempo; - propTimediv.cbStruct = sizeof(MIDIPROPTIMEDIV); - propTimediv.dwTimeDiv = division; - - if (midiLastDivision != division) { - // changing the division means halting the stream - WinMMDrv_MIDI_HaltPlayback(); - - rv = midiStreamProperty(midiStream, (LPBYTE) &propTimediv, MIDIPROP_SET | MIDIPROP_TIMEDIV); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "WinMM MIDI_SetTempo midiStreamProperty timediv"); - } - } - - rv = midiStreamProperty(midiStream, (LPBYTE) &propTempo, MIDIPROP_SET | MIDIPROP_TEMPO); - if (rv != MMSYSERR_NOERROR) { - midi_error(rv, "WinMM MIDI_SetTempo midiStreamProperty tempo"); - } - - if (midiLastDivision != division) { - if (running && WinMMDrv_MIDI_StartPlayback(midiThreadService) != WinMMErr_Ok) { - return; - } - - midiLastDivision = division; - } - - midiThreadQueueTicks = (int) ceil( ( ( (double) tempo * (double) division ) / 60.0 ) / - (double) THREAD_QUEUE_INTERVAL ); - if (midiThreadQueueTicks <= 0) { - midiThreadQueueTicks = 1; - } -} - -void WinMMDrv_MIDI_Lock(void) -{ - DWORD err; - - err = WaitForSingleObject(midiMutex, INFINITE); - if (err != WAIT_OBJECT_0) { - MV_Printf("WinMM midiMutex lock: wfso %d\n", (int) err); - } -} - -void WinMMDrv_MIDI_Unlock(void) -{ - ReleaseMutex(midiMutex); -} - -// vim:ts=4:sw=4:expandtab: diff --git a/source/audiolib/src/driver_winmm.h b/source/audiolib/src/driver_winmm.h deleted file mode 100644 index 51c71d2b6..000000000 --- a/source/audiolib/src/driver_winmm.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - -#include "midifuncs.h" - -int WinMMDrv_GetError(void); -const char *WinMMDrv_ErrorString( int ErrorNumber ); - -int WinMMDrv_MIDI_Init(midifuncs *); -void WinMMDrv_MIDI_Shutdown(void); -int WinMMDrv_MIDI_StartPlayback(void (*service)(void)); -void WinMMDrv_MIDI_HaltPlayback(void); -void WinMMDrv_MIDI_SetTempo(int tempo, int division); -void WinMMDrv_MIDI_Lock(void); -void WinMMDrv_MIDI_Unlock(void); - diff --git a/source/audiolib/src/drivers.cpp b/source/audiolib/src/drivers.cpp deleted file mode 100644 index 57d90f12b..000000000 --- a/source/audiolib/src/drivers.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - -/** - * Abstraction layer for hiding the various supported sound devices - * behind a common and opaque interface called on by MultiVoc. - */ - -#include "drivers.h" - -#include "driver_adlib.h" - -#ifdef RENDERTYPESDL -# include "driver_sdl.h" -#endif - -#ifdef _WIN32 -# include "driver_directsound.h" -# include "driver_winmm.h" -#endif - -int ASS_PCMSoundDriver = ASS_AutoDetect; -int ASS_MIDISoundDriver = ASS_AutoDetect; -int ASS_EMIDICard = -1; - -#define UNSUPPORTED_PCM nullptr,nullptr,nullptr,nullptr,nullptr,nullptr -#define UNSUPPORTED_MIDI nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr -#define UNSUPPORTED_COMPLETELY nullptr, nullptr, UNSUPPORTED_PCM, UNSUPPORTED_MIDI - -static struct { - const char * DriverName; - - int (*GetError)(void); - const char *(*ErrorString)(int); - - int (*PCM_Init)(int *, int *, void *); - void (*PCM_Shutdown)(void); - int (*PCM_BeginPlayback)(char *, int, int, void (*)(void)); - void (*PCM_StopPlayback)(void); - void (*PCM_Lock)(void); - void (*PCM_Unlock)(void); - - int (*MIDI_Init)(midifuncs *); - void (*MIDI_Shutdown)(void); - int (*MIDI_StartPlayback)(void (*service)(void)); - void (*MIDI_HaltPlayback)(void); - void (*MIDI_SetTempo)(int tempo, int division); - void (*MIDI_Lock)(void); - void (*MIDI_Unlock)(void); -} SoundDrivers[ASS_NumSoundCards] = { - - - // Simple DirectMedia Layer - { - "SDL", - #ifdef RENDERTYPESDL - SDLDrv_GetError, - SDLDrv_ErrorString, - SDLDrv_PCM_Init, - SDLDrv_PCM_Shutdown, - SDLDrv_PCM_BeginPlayback, - SDLDrv_PCM_StopPlayback, - SDLDrv_PCM_Lock, - SDLDrv_PCM_Unlock, - UNSUPPORTED_MIDI, - #else - UNSUPPORTED_COMPLETELY - #endif - }, - - // Windows DirectSound - { - "DirectSound", - #ifdef RENDERTYPEWIN - DirectSoundDrv_GetError, - DirectSoundDrv_ErrorString, - DirectSoundDrv_PCM_Init, - DirectSoundDrv_PCM_Shutdown, - DirectSoundDrv_PCM_BeginPlayback, - DirectSoundDrv_PCM_StopPlayback, - DirectSoundDrv_PCM_Lock, - DirectSoundDrv_PCM_Unlock, - UNSUPPORTED_MIDI, - #else - UNSUPPORTED_COMPLETELY - #endif - }, - - // OPL3 emulation - { - "Nuked OPL3 AdLib emulator", - AdLibDrv_GetError, - AdLibDrv_ErrorString, - - UNSUPPORTED_PCM, - - AdLibDrv_MIDI_Init, - AdLibDrv_MIDI_Shutdown, - AdLibDrv_MIDI_StartPlayback, - AdLibDrv_MIDI_HaltPlayback, - AdLibDrv_MIDI_SetTempo, - nullptr, - nullptr, - }, - - // Windows MultiMedia system - { - "WinMM", - #ifdef _WIN32 - WinMMDrv_GetError, - WinMMDrv_ErrorString, - - UNSUPPORTED_PCM, - - WinMMDrv_MIDI_Init, - WinMMDrv_MIDI_Shutdown, - WinMMDrv_MIDI_StartPlayback, - WinMMDrv_MIDI_HaltPlayback, - WinMMDrv_MIDI_SetTempo, - WinMMDrv_MIDI_Lock, - WinMMDrv_MIDI_Unlock, - #else - UNSUPPORTED_COMPLETELY - #endif - }, -}; - - -int SoundDriver_IsPCMSupported(int driver) { return (SoundDrivers[driver].PCM_Init != 0); } -int SoundDriver_IsMIDISupported(int driver) { return (SoundDrivers[driver].MIDI_Init != 0); } -const char *SoundDriver_GetName(int driver) { return SoundDrivers[driver].DriverName; } - -int SoundDriver_PCM_GetError(void) -{ - if (!SoundDriver_IsPCMSupported(ASS_PCMSoundDriver)) - return -1; - - return SoundDrivers[ASS_PCMSoundDriver].GetError(); -} - -const char * SoundDriver_PCM_ErrorString( int ErrorNumber ) -{ - if (ASS_PCMSoundDriver < 0 || ASS_PCMSoundDriver >= ASS_NumSoundCards) - return "No sound driver selected."; - - if (!SoundDriver_IsPCMSupported(ASS_PCMSoundDriver)) - return "Unsupported sound driver selected."; - - return SoundDrivers[ASS_PCMSoundDriver].ErrorString(ErrorNumber); -} - -int SoundDriver_MIDI_GetError(void) -{ - if (!SoundDriver_IsMIDISupported(ASS_MIDISoundDriver)) - return -1; - - return SoundDrivers[ASS_MIDISoundDriver].GetError(); -} - -const char * SoundDriver_MIDI_ErrorString( int ErrorNumber ) -{ - if (ASS_MIDISoundDriver < 0 || ASS_MIDISoundDriver >= ASS_NumSoundCards) - return "No sound driver selected."; - - if (!SoundDriver_IsMIDISupported(ASS_MIDISoundDriver)) - return "Unsupported sound driver selected."; - - return SoundDrivers[ASS_MIDISoundDriver].ErrorString(ErrorNumber); -} - -int SoundDriver_PCM_Init(int *mixrate, int *numchannels, void *initdata) -{ - return SoundDrivers[ASS_PCMSoundDriver].PCM_Init(mixrate, numchannels, initdata); -} - -int SoundDriver_PCM_BeginPlayback(char *BufferStart, int BufferSize, int NumDivisions, void (*CallBackFunc)(void)) -{ - return SoundDrivers[ASS_PCMSoundDriver].PCM_BeginPlayback(BufferStart, BufferSize, NumDivisions, CallBackFunc); -} - -void SoundDriver_PCM_Shutdown(void) { SoundDrivers[ASS_PCMSoundDriver].PCM_Shutdown(); } -void SoundDriver_PCM_StopPlayback(void) { SoundDrivers[ASS_PCMSoundDriver].PCM_StopPlayback(); } -void SoundDriver_PCM_Lock(void) { SoundDrivers[ASS_PCMSoundDriver].PCM_Lock(); } -void SoundDriver_PCM_Unlock(void) { SoundDrivers[ASS_PCMSoundDriver].PCM_Unlock(); } -int SoundDriver_MIDI_Init(midifuncs *funcs) { return SoundDrivers[ASS_MIDISoundDriver].MIDI_Init(funcs); } -int SoundDriver_MIDI_StartPlayback(void (*service)(void)) { return SoundDrivers[ASS_MIDISoundDriver].MIDI_StartPlayback(service); } -void SoundDriver_MIDI_Shutdown(void) { SoundDrivers[ASS_MIDISoundDriver].MIDI_Shutdown(); } -void SoundDriver_MIDI_HaltPlayback(void) { SoundDrivers[ASS_MIDISoundDriver].MIDI_HaltPlayback(); } -void SoundDriver_MIDI_SetTempo(int tempo, int division) { SoundDrivers[ASS_MIDISoundDriver].MIDI_SetTempo(tempo, division); } -void SoundDriver_MIDI_Lock(void) { if (SoundDrivers[ASS_MIDISoundDriver].MIDI_Lock) SoundDrivers[ASS_MIDISoundDriver].MIDI_Lock(); } -void SoundDriver_MIDI_Unlock(void) { if (SoundDrivers[ASS_MIDISoundDriver].MIDI_Unlock) SoundDrivers[ASS_MIDISoundDriver].MIDI_Unlock(); } - -// vim:ts=4:sw=4:expandtab: diff --git a/source/audiolib/src/formats.cpp b/source/audiolib/src/formats.cpp deleted file mode 100644 index 5fcfedf56..000000000 --- a/source/audiolib/src/formats.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - Copyright (C) 2015 EDuke32 developers - Copyright (C) 2015 Voidpoint, LLC - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -/** - * Raw, WAV, and VOC source support for MultiVoc - */ - -#include "_multivc.h" -#include "compat.h" -#include "multivoc.h" -#include "pitch.h" -#include "pragmas.h" - -static playbackstatus MV_GetNextWAVBlock(VoiceNode *voice) -{ - if (voice->BlockLength == 0) - { - if (voice->LoopStart == nullptr) - return NoMoreData; - - voice->BlockLength = voice->LoopSize; - voice->NextBlock = voice->LoopStart; - voice->length = 0; - voice->position = 0; - } - - voice->sound = voice->NextBlock; - voice->position -= voice->length; - voice->length = min(voice->BlockLength, 0x8000u); - voice->NextBlock += voice->length * ((voice->channels * voice->bits) >> 3); - voice->BlockLength -= voice->length; - voice->length <<= 16; - - return KeepPlaying; -} - -static playbackstatus MV_GetNextVOCBlock(VoiceNode *voice) -{ - size_t blocklength = 0; - uint32_t samplespeed = 0; // XXX: compiler-happy on synthesis - uint32_t tc = 0; - unsigned BitsPerSample; - unsigned Channels; - unsigned Format; - - if (voice->BlockLength > 0) - { - voice->position -= voice->length; - voice->sound += (voice->length >> 16) * ((voice->channels * voice->bits) >> 3); - voice->length = min(voice->BlockLength, 0x8000u); - voice->BlockLength -= voice->length; - voice->length <<= 16; - return KeepPlaying; - } - - auto ptr = (uint8_t const *)voice->NextBlock; - - voice->Paused = FALSE; - - int voicemode = 0; - int blocktype = 0; - int lastblocktype = 0; - int packtype = 0; - - int done = FALSE; - - do - { - // Stop playing if we get a null pointer - if (ptr == nullptr) - { - done = 2; - break; - } - - // terminator is not mandatory according to - // http://wiki.multimedia.cx/index.php?title=Creative_Voice - - if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength) - blocktype = 0; // fake a terminator - else - blocktype = *ptr; - - if (blocktype != 0) - blocklength = ptr[1]|(ptr[2]<<8)|(ptr[3]<<16); - else - blocklength = 0; - // would need one byte pad at end of alloc'd region: -// blocklength = B_LITTLE32(*(uint32_t *)(ptr + 1)) & 0x00ffffff; - - ptr += 4; - - switch (blocktype) - { - case 0 : -end_of_data: - // End of data - if ((voice->LoopStart == nullptr) || - ((intptr_t) voice->LoopStart >= ((intptr_t) ptr - 4))) - { - done = 2; - } - else - { - voice->NextBlock = voice->LoopStart; - voice->BlockLength = 0; - voice->position = 0; - return MV_GetNextVOCBlock(voice); - } - break; - - case 1 : - // Sound data block - voice->bits = 8; - voice->channels = voicemode + 1; - if (lastblocktype != 8) - { - tc = (uint32_t)*ptr << 8; - packtype = *(ptr + 1); - } - - ptr += 2; - blocklength -= 2; - - samplespeed = 256000000L / (voice->channels * (65536 - tc)); - - // Skip packed or stereo data - if ((packtype != 0) || (voicemode != 0 && voicemode != 1)) - ptr += blocklength; - else - done = TRUE; - - if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength) - goto end_of_data; - - voicemode = 0; - break; - - case 2 : - // Sound continuation block - samplespeed = voice->SamplingRate; - done = TRUE; - break; - - case 3 : - // Silence - case 4 : - // Marker - case 5 : - // ASCII string - // All not implemented. - ptr += blocklength; - break; - - case 6 : - // Repeat begin - if (voice->LoopEnd == nullptr) - { - voice->LoopCount = B_LITTLE16(*(uint16_t const *)ptr); - voice->LoopStart = (char *)((intptr_t) ptr + blocklength); - } - ptr += blocklength; - break; - - case 7 : - // Repeat end - ptr += blocklength; - if (lastblocktype == 6) - voice->LoopCount = 0; - else - { - if ((voice->LoopCount > 0) && (voice->LoopStart != nullptr)) - { - ptr = (uint8_t const *) voice->LoopStart; - - if (voice->LoopCount < 0xffff) - { - if (--voice->LoopCount == 0) - voice->LoopStart = nullptr; - } - } - } - break; - - case 8 : - // Extended block - voice->bits = 8; - voice->channels = 1; - tc = B_LITTLE16(*(uint16_t const *)ptr); - packtype = *(ptr + 2); - voicemode = *(ptr + 3); - ptr += blocklength; - break; - - case 9 : - // New sound data block - samplespeed = B_LITTLE32(*(uint32_t const *)ptr); - BitsPerSample = (unsigned)*(ptr + 4); - Channels = (unsigned)*(ptr + 5); - Format = (unsigned)B_LITTLE16(*(uint16_t const *)(ptr + 6)); - - if ((BitsPerSample == 8) && (Channels == 1 || Channels == 2) && (Format == VOC_8BIT)) - { - ptr += 12; - blocklength -= 12; - voice->bits = 8; - voice->channels = Channels; - done = TRUE; - } - else if ((BitsPerSample == 16) && (Channels == 1 || Channels == 2) && (Format == VOC_16BIT)) - { - ptr += 12; - blocklength -= 12; - voice->bits = 16; - voice->channels = Channels; - done = TRUE; - } - else - { - ptr += blocklength; - } - - // CAUTION: - // SNAKRM.VOC is corrupt! blocklength gets us beyond the - // end of the file. - if (ptr - (uint8_t *)voice->rawdataptr >= voice->ptrlength) - goto end_of_data; - - break; - - default : - // Unknown data. Probably not a VOC file. - done = 2; - break; - } - - lastblocktype = blocktype; - } - while (!done); - - if (done != 2) - { - voice->NextBlock = (char const *)ptr + blocklength; - voice->sound = (char const *)ptr; - - // CODEDUP multivoc.c MV_SetVoicePitch - voice->SamplingRate = samplespeed; - voice->RateScale = divideu32(voice->SamplingRate * voice->PitchScale, MV_MixRate); - - // Multiply by MV_MIXBUFFERSIZE - 1 - voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - - voice->RateScale; - - if (voice->LoopEnd != nullptr) - { - if (blocklength > (uintptr_t)voice->LoopEnd) - blocklength = (uintptr_t)voice->LoopEnd; - else - voice->LoopEnd = (char *)blocklength; - - voice->LoopStart = voice->sound + (uintptr_t)voice->LoopStart; - voice->LoopEnd = voice->sound + (uintptr_t)voice->LoopEnd; - voice->LoopSize = voice->LoopEnd - voice->LoopStart; - } - - if (voice->bits == 16) - blocklength /= 2; - - if (voice->channels == 2) - blocklength /= 2; - - voice->position = 0; - voice->length = min(blocklength, 0x8000u); - voice->BlockLength = blocklength - voice->length; - voice->length <<= 16; - - MV_SetVoiceMixMode(voice); - - return KeepPlaying; - } - - return NoMoreData; -} - -static playbackstatus MV_GetNextRAWBlock(VoiceNode *voice) -{ - if (voice->BlockLength == 0) - { - if (voice->LoopStart == NULL) - return NoMoreData; - - voice->BlockLength = voice->LoopSize; - voice->NextBlock = voice->LoopStart; - voice->length = 0; - voice->position = 0; - } - - voice->sound = voice->NextBlock; - voice->position -= voice->length; - voice->length = min(voice->BlockLength, 0x8000u); - voice->NextBlock += voice->length * (voice->channels * voice->bits / 8); - voice->BlockLength -= voice->length; - voice->length <<= 16; - - return KeepPlaying; -} - -int MV_PlayWAV3D(char *ptr, uint32_t length, int loophow, int pitchoffset, int angle, int distance, - int priority, float volume, intptr_t callbackval) -{ - if (!MV_Installed) - return MV_Error; - - if (distance < 0) - { - distance = -distance; - angle += MV_NUMPANPOSITIONS / 2; - } - - int const vol = MIX_VOLUME(distance); - - // Ensure angle is within 0 - 127 - angle &= MV_MAXPANPOSITION; - - return MV_PlayWAV(ptr, length, loophow, -1, pitchoffset, max(0, 255 - distance), - MV_PanTable[ angle ][ vol ].left, MV_PanTable[ angle ][ vol ].right, priority, volume, callbackval); -} - -int MV_PlayWAV(char *ptr, uint32_t length, int loopstart, int loopend, int pitchoffset, int vol, - int left, int right, int priority, float volume, intptr_t callbackval) -{ - if (!MV_Installed) - return MV_Error; - - riff_header riff; - memcpy(&riff, ptr, sizeof(riff_header)); - riff.file_size = B_LITTLE32(riff.file_size); - riff.format_size = B_LITTLE32(riff.format_size); - - if ((memcmp(riff.RIFF, "RIFF", 4) != 0) || (memcmp(riff.WAVE, "WAVE", 4) != 0) || (memcmp(riff.fmt, "fmt ", 4) != 0)) - return MV_SetErrorCode(MV_InvalidFile); - - format_header format; - memcpy(&format, ptr + sizeof(riff_header), sizeof(format_header)); - format.wFormatTag = B_LITTLE16(format.wFormatTag); - format.nChannels = B_LITTLE16(format.nChannels); - format.nSamplesPerSec = B_LITTLE32(format.nSamplesPerSec); - format.nAvgBytesPerSec = B_LITTLE32(format.nAvgBytesPerSec); - format.nBlockAlign = B_LITTLE16(format.nBlockAlign); - format.nBitsPerSample = B_LITTLE16(format.nBitsPerSample); - - data_header data; - memcpy(&data, ptr + sizeof(riff_header) + riff.format_size, sizeof(data_header)); - data.size = B_LITTLE32(data.size); - - // Check if it's PCM data. - if (format.wFormatTag != 1 || (format.nChannels != 1 && format.nChannels != 2) || - ((format.nBitsPerSample != 8) && (format.nBitsPerSample != 16)) || memcmp(data.DATA, "data", 4) != 0) - return MV_SetErrorCode(MV_InvalidFile); - - // Request a voice from the voice pool - - VoiceNode *voice = MV_AllocVoice(priority); - - if (voice == nullptr) - return MV_SetErrorCode(MV_NoVoices); - - voice->wavetype = FMT_WAV; - voice->bits = format.nBitsPerSample; - voice->channels = format.nChannels; - voice->GetSound = MV_GetNextWAVBlock; - - int blocklen = data.size; - - if (voice->bits == 16) - { - data.size &= ~1; - blocklen /= 2; - } - - if (voice->channels == 2) - { - data.size &= ~1; - blocklen /= 2; - } - - voice->rawdataptr = (uint8_t *)ptr; - voice->ptrlength = length; - voice->Paused = FALSE; - voice->LoopCount = 0; - voice->position = 0; - voice->length = 0; - voice->BlockLength = blocklen; - voice->NextBlock = (char *)((intptr_t) ptr + sizeof(riff_header) + riff.format_size + sizeof(data_header)); - voice->next = nullptr; - voice->prev = nullptr; - voice->priority = priority; - voice->callbackval = callbackval; - voice->LoopStart = loopstart >= 0 ? voice->NextBlock : nullptr; - voice->LoopEnd = nullptr; - voice->LoopSize = loopend > 0 ? loopend - loopstart + 1 : blocklen; - - MV_SetVoicePitch(voice, format.nSamplesPerSec, pitchoffset); - MV_SetVoiceVolume(voice, vol, left, right, volume); - MV_PlayVoice(voice); - - return voice->handle; -} - -int MV_PlayVOC3D(char *ptr, uint32_t length, int loophow, int pitchoffset, int angle, - int distance, int priority, float volume, intptr_t callbackval) -{ - if (!MV_Installed) - return MV_Error; - - if (distance < 0) - { - distance = -distance; - angle += MV_NUMPANPOSITIONS / 2; - } - - int const vol = MIX_VOLUME(distance); - - // Ensure angle is within 0 - 127 - angle &= MV_MAXPANPOSITION; - - return MV_PlayVOC(ptr, length, loophow, -1, pitchoffset, max(0, 255 - distance), - MV_PanTable[ angle ][ vol ].left, MV_PanTable[ angle ][ vol ].right, priority, volume, callbackval); -} - -int MV_PlayVOC(char *ptr, uint32_t length, int loopstart, int loopend, int pitchoffset, int vol, - int left, int right, int priority, float volume, intptr_t callbackval) -{ - if (!MV_Installed) - return MV_Error; - - // Make sure it looks like a valid VOC file. - if (memcmp(ptr, "Creative Voice File", 19) != 0) - return MV_SetErrorCode(MV_InvalidFile); - - // Request a voice from the voice pool - VoiceNode *voice = MV_AllocVoice(priority); - - if (voice == nullptr) - return MV_SetErrorCode(MV_NoVoices); - - voice->rawdataptr = (uint8_t *)ptr; - voice->ptrlength = length; - voice->Paused = FALSE; - voice->wavetype = FMT_VOC; - voice->bits = 8; - voice->channels = 1; - voice->GetSound = MV_GetNextVOCBlock; - voice->NextBlock = ptr + B_LITTLE16(*(uint16_t *)(ptr + 0x14)); - voice->LoopCount = 0; - voice->BlockLength = 0; - voice->PitchScale = PITCH_GetScale(pitchoffset); - voice->length = 0; - voice->next = nullptr; - voice->prev = nullptr; - voice->priority = priority; - voice->callbackval = callbackval; - voice->LoopStart = loopstart >= 0 ? voice->NextBlock : nullptr; - voice->LoopEnd = nullptr; - voice->LoopSize = loopend - loopstart + 1; - - voice->volume = volume; - - MV_SetVoiceVolume(voice, vol, left, right, volume); - MV_PlayVoice(voice); - - return voice->handle; -} - -int MV_PlayRAW(char *ptr, uint32_t length, int rate, char *loopstart, char *loopend, int pitchoffset, int vol, - int left, int right, int priority, float volume, intptr_t callbackval) -{ - if (!MV_Installed) - return MV_Error; - - // Request a voice from the voice pool - VoiceNode *voice = MV_AllocVoice(priority); - - if (voice == NULL) - { - MV_SetErrorCode(MV_NoVoices); - return MV_Error; - } - - voice->rawdataptr = (uint8_t *)ptr; - voice->ptrlength = length; - voice->Paused = FALSE; - voice->wavetype = FMT_RAW; - voice->bits = 8; - voice->channels = 1; - voice->GetSound = MV_GetNextRAWBlock; - voice->NextBlock = ptr; - voice->LoopCount = 0; - voice->position = 0; - voice->BlockLength = length; - voice->PitchScale = PITCH_GetScale(pitchoffset); - voice->length = 0; - voice->next = NULL; - voice->prev = NULL; - voice->priority = priority; - voice->callbackval = callbackval; - voice->LoopStart = loopstart; - voice->LoopEnd = loopend; - voice->LoopSize = loopend - loopstart + 1; - - voice->volume = volume; - - MV_SetVoicePitch(voice, rate, pitchoffset); - MV_SetVoiceVolume(voice, vol, left, right, volume); - MV_PlayVoice(voice); - - return voice->handle; -} diff --git a/source/audiolib/src/fx_man.cpp b/source/audiolib/src/fx_man.cpp deleted file mode 100644 index d9ad4cc18..000000000 --- a/source/audiolib/src/fx_man.cpp +++ /dev/null @@ -1,258 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2016 EDuke32 developers and contributors - -This file is part of EDuke32. - -EDuke32 is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- - -#include "fx_man.h" - -#include "compat.h" -#include "drivers.h" -#include "driver_adlib.h" -#include "midi.h" -#include "multivoc.h" -#include "osd.h" - -int FX_ErrorCode = FX_Ok; -int FX_Installed; - -const char *FX_ErrorString(int const ErrorNumber) -{ - const char *ErrorString; - - switch (ErrorNumber) - { - case FX_Warning: - case FX_Error: ErrorString = FX_ErrorString(FX_ErrorCode); break; - case FX_Ok: ErrorString = "Fx ok."; break; - case FX_MultiVocError: ErrorString = MV_ErrorString(MV_Error); break; - default: ErrorString = "Unknown Fx error code."; break; - } - - return ErrorString; -} - - -int FX_Init(int numvoices, int numchannels, int mixrate, void *initdata) -{ - if (FX_Installed) - FX_Shutdown(); - - int SoundCard = ASS_AutoDetect; - - if (SoundCard == ASS_AutoDetect) - { -#if defined RENDERTYPESDL - SoundCard = ASS_SDL; -#elif defined RENDERTYPEWIN - SoundCard = ASS_DirectSound; -#endif - } - - if (SoundCard < 0 || SoundCard >= ASS_NumSoundCards) - { - FX_SetErrorCode(FX_InvalidCard); - return FX_Error; - } - - if (SoundDriver_IsPCMSupported(SoundCard) == 0) - { - // unsupported cards fall back to no sound - FX_SetErrorCode(FX_InvalidCard); - return FX_Error; - } - - int status = FX_Ok; - - if (MV_Init(SoundCard, mixrate, numvoices, numchannels, initdata) != MV_Ok) - { - FX_SetErrorCode(FX_MultiVocError); - status = FX_Error; - } - - if (status == FX_Ok) - FX_Installed = TRUE; - - return status; -} - -int FX_Shutdown(void) -{ - if (!FX_Installed) - return FX_Ok; - - int status = MV_Shutdown(); - - if (status != MV_Ok) - { - FX_SetErrorCode(FX_MultiVocError); - status = FX_Error; - } - - FX_Installed = FALSE; - - return status; -} - -int FX_GetDevice() -{ - return ASS_PCMSoundDriver; -} - -static wavefmt_t FX_DetectFormat(char const * const ptr, uint32_t length) -{ - if (length < 12) - return FMT_UNKNOWN; - - wavefmt_t fmt = FMT_UNKNOWN; - - switch (B_LITTLE32(*(int const *)ptr)) - { - case 'C' + ('r' << 8) + ('e' << 16) + ('a' << 24): // Crea - fmt = FMT_VOC; - break; - case 'O' + ('g' << 8) + ('g' << 16) + ('S' << 24): // OggS - fmt = FMT_VORBIS; - break; - case 'R' + ('I' << 8) + ('F' << 16) + ('F' << 24): // RIFF - switch (B_LITTLE32(*(int const *)(ptr + 8))) - { - case 'W' + ('A' << 8) + ('V' << 16) + ('E' << 24): // WAVE - fmt = FMT_WAV; - break; - } - break; - default: - break; - } - - return fmt; -} - -int FX_Play(char *ptr, uint32_t ptrlength, int loopstart, int loopend, int pitchoffset, - int vol, int left, int right, int priority, float volume, intptr_t callbackval) -{ - static constexpr decltype(MV_PlayVOC) *func[] = - { nullptr, nullptr, MV_PlayVOC, MV_PlayWAV, nullptr, nullptr, MV_PlayVorbis, nullptr, nullptr, nullptr }; - - //EDUKE32_STATIC_ASSERT(FMT_MAX == ARRAY_SIZE(func)); - - wavefmt_t const fmt = FX_DetectFormat(ptr, ptrlength); - - int handle = - (func[fmt]) ? func[fmt](ptr, ptrlength, loopstart, loopend, pitchoffset, vol, left, right, priority, volume, callbackval) : -1; - - if (handle <= MV_Ok) - { - FX_SetErrorCode(FX_MultiVocError); - handle = FX_Warning; - } - - return handle; -} - -int FX_Play3D(char *ptr, uint32_t ptrlength, int loophow, int pitchoffset, int angle, int distance, - int priority, float volume, intptr_t callbackval) -{ - static constexpr decltype(MV_PlayVOC3D) *func[] = - { nullptr, nullptr, MV_PlayVOC3D, MV_PlayWAV3D, nullptr, nullptr, MV_PlayVorbis3D, nullptr, nullptr, nullptr }; - - //EDUKE32_STATIC_ASSERT(FMT_MAX == ARRAY_SIZE(func)); - - wavefmt_t const fmt = FX_DetectFormat(ptr, ptrlength); - - int handle = - (func[fmt]) ? func[fmt](ptr, ptrlength, loophow, pitchoffset, angle, distance, priority, volume, callbackval) : -1; - - if (handle <= MV_Ok) - { - FX_SetErrorCode(FX_MultiVocError); - handle = FX_Warning; - } - - return handle; -} - -int FX_PlayRaw(char *ptr, uint32_t ptrlength, int rate, int pitchoffset, int vol, - int left, int right, int priority, float volume, intptr_t callbackval) -{ - int handle = MV_PlayRAW(ptr, ptrlength, rate, NULL, NULL, pitchoffset, vol, left, right, priority, volume, callbackval); - - if (handle <= MV_Ok) - { - FX_SetErrorCode(FX_MultiVocError); - handle = FX_Warning; - } - - return handle; -} - -int FX_PlayLoopedRaw(char *ptr, uint32_t ptrlength, char *loopstart, char *loopend, int rate, - int pitchoffset, int vol, int left, int right, int priority, float volume, intptr_t callbackval) -{ - int handle = MV_PlayRAW(ptr, ptrlength, rate, loopstart, loopend, pitchoffset, vol, left, right, priority, volume, callbackval); - - if (handle <= MV_Ok) - { - FX_SetErrorCode(FX_MultiVocError); - handle = FX_Warning; - } - - return handle; -} - -int FX_SetPrintf(void (*function)(const char *, ...)) -{ - MV_SetPrintf(function); - - return FX_Ok; -} - -/*--------------------------------------------------------------------- - Function: FX_StartDemandFeedPlayback - - Plays a digitized sound from a user controlled buffering system. ----------------------------------------------------------------------*/ - -int FX_StartDemandFeedPlayback -( - void (*function)(const char** ptr, uint32_t* length), - int rate, - int pitchoffset, - int vol, - int left, - int right, - int priority, - fix16_t volume, - uint32_t callbackval -) - -{ - int handle; - - handle = MV_StartDemandFeedPlayback(function, rate, - pitchoffset, vol, left, right, priority, volume, callbackval); - if (handle < MV_Ok) - { - FX_SetErrorCode(FX_MultiVocError); - handle = FX_Warning; - } - - return(handle); -} \ No newline at end of file diff --git a/source/audiolib/src/gmtimbre.cpp b/source/audiolib/src/gmtimbre.cpp deleted file mode 100644 index a363e75e7..000000000 --- a/source/audiolib/src/gmtimbre.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include -#include "al_midi.h" - -AdLibTimbre ADLIB_TimbreBank[256] = - { - { { 33, 33 }, { 143, 6 }, { 242, 242 }, { 69, 118 }, { 0, 0 }, 8, 0, 0 }, - { { 49, 33 }, { 75, 0 }, { 242, 242 }, { 84, 86 }, { 0, 0 }, 8, 0, 0 }, - { { 49, 33 }, { 73, 0 }, { 242, 242 }, { 85, 118 }, { 0, 0 }, 8, 0, 0 }, - { { 177, 97 }, { 14, 0 }, { 242, 243 }, { 59, 11 }, { 0, 0 }, 6, 0, 0 }, - { { 1, 33 }, { 87, 0 }, { 241, 241 }, { 56, 40 }, { 0, 0 }, 0, 0, 0 }, - { { 1, 33 }, { 147, 0 }, { 241, 241 }, { 56, 40 }, { 0, 0 }, 0, 0, 0 }, - { { 33, 54 }, { 128, 14 }, { 162, 241 }, { 1, 213 }, { 0, 0 }, 8, 0, 0 }, - { { 1, 1 }, { 146, 0 }, { 194, 194 }, { 168, 88 }, { 0, 0 }, 10, 0, 0 }, - { { 12, 129 }, { 92, 0 }, { 246, 243 }, { 84, 181 }, { 0, 0 }, 0, 0, 0 }, - { { 7, 17 }, { 151, 128 }, { 246, 245 }, { 50, 17 }, { 0, 0 }, 2, 0, 0 }, - { { 23, 1 }, { 33, 0 }, { 86, 246 }, { 4, 4 }, { 0, 0 }, 2, 0, 0 }, - { { 24, 129 }, { 98, 0 }, { 243, 242 }, { 230, 246 }, { 0, 0 }, 0, 0, 0 }, - { { 24, 33 }, { 35, 0 }, { 247, 229 }, { 85, 216 }, { 0, 0 }, 0, 0, 0 }, - { { 21, 1 }, { 145, 0 }, { 246, 246 }, { 166, 230 }, { 0, 0 }, 4, 0, 0 }, - { { 69, 129 }, { 89, 128 }, { 211, 163 }, { 130, 227 }, { 0, 0 }, 12, 0, 0 }, - { { 3, 129 }, { 73, 128 }, { 116, 179 }, { 85, 5 }, { 1, 0 }, 4, 0, 0 }, - { { 113, 49 }, { 146, 0 }, { 246, 241 }, { 20, 7 }, { 0, 0 }, 2, 0, 0 }, - { { 114, 48 }, { 20, 0 }, { 199, 199 }, { 88, 8 }, { 0, 0 }, 2, 0, 0 }, - { { 112, 177 }, { 68, 0 }, { 170, 138 }, { 24, 8 }, { 0, 0 }, 4, 0, 0 }, - { { 35, 177 }, { 147, 0 }, { 151, 85 }, { 35, 20 }, { 1, 0 }, 4, 0, 0 }, - { { 97, 177 }, { 19, 128 }, { 151, 85 }, { 4, 4 }, { 1, 0 }, 0, 0, 0 }, - { { 36, 177 }, { 72, 0 }, { 152, 70 }, { 42, 26 }, { 1, 0 }, 12, 0, 0 }, - { { 97, 33 }, { 19, 0 }, { 145, 97 }, { 6, 7 }, { 1, 0 }, 10, 0, 0 }, - { { 33, 161 }, { 19, 137 }, { 113, 97 }, { 6, 7 }, { 0, 0 }, 6, 0, 0 }, - { { 2, 65 }, { 156, 128 }, { 243, 243 }, { 148, 200 }, { 1, 0 }, 12, 0, 0 }, - { { 3, 17 }, { 84, 0 }, { 243, 241 }, { 154, 231 }, { 1, 0 }, 12, 0, 0 }, - { { 35, 33 }, { 95, 0 }, { 241, 242 }, { 58, 248 }, { 0, 0 }, 0, 0, 0 }, - { { 3, 33 }, { 135, 128 }, { 246, 243 }, { 34, 243 }, { 1, 0 }, 6, 0, 0 }, - { { 3, 33 }, { 71, 0 }, { 249, 246 }, { 84, 58 }, { 0, 0 }, 0, 0, 0 }, - { { 35, 33 }, { 72, 0 }, { 149, 132 }, { 25, 25 }, { 1, 0 }, 8, 0, 0 }, - { { 35, 33 }, { 74, 0 }, { 149, 148 }, { 25, 25 }, { 1, 0 }, 8, 0, 0 }, - { { 9, 132 }, { 161, 128 }, { 32, 209 }, { 79, 248 }, { 0, 0 }, 8, 0, 0 }, - { { 33, 162 }, { 30, 0 }, { 148, 195 }, { 6, 166 }, { 0, 0 }, 2, 0, 0 }, - { { 49, 49 }, { 18, 0 }, { 241, 241 }, { 40, 24 }, { 0, 0 }, 10, 0, 0 }, - { { 49, 49 }, { 141, 0 }, { 241, 241 }, { 232, 120 }, { 0, 0 }, 10, 0, 0 }, - { { 49, 50 }, { 91, 0 }, { 81, 113 }, { 40, 72 }, { 0, 0 }, 12, 0, 0 }, - { { 1, 33 }, { 139, 64 }, { 161, 242 }, { 154, 223 }, { 0, 0 }, 8, 0, 0 }, - { { 1, 33 }, { 137, 64 }, { 161, 242 }, { 154, 223 }, { 0, 0 }, 8, 0, 0 }, - { { 49, 49 }, { 139, 0 }, { 244, 241 }, { 232, 120 }, { 0, 0 }, 10, 0, 0 }, - { { 49, 49 }, { 18, 0 }, { 241, 241 }, { 40, 24 }, { 0, 0 }, 10, 0, 0 }, - { { 49, 33 }, { 21, 0 }, { 221, 86 }, { 19, 38 }, { 1, 0 }, 8, 0, 0 }, - { { 49, 33 }, { 22, 0 }, { 221, 102 }, { 19, 6 }, { 1, 0 }, 8, 0, 0 }, - { { 113, 49 }, { 73, 0 }, { 209, 97 }, { 28, 12 }, { 1, 0 }, 8, 0, 0 }, - { { 33, 35 }, { 77, 128 }, { 113, 114 }, { 18, 6 }, { 1, 0 }, 2, 0, 0 }, - { { 241, 225 }, { 64, 0 }, { 241, 111 }, { 33, 22 }, { 1, 0 }, 2, 0, 0 }, - { { 2, 1 }, { 26, 128 }, { 245, 133 }, { 117, 53 }, { 1, 0 }, 0, 0, 0 }, - { { 2, 1 }, { 29, 128 }, { 245, 243 }, { 117, 244 }, { 1, 0 }, 0, 0, 0 }, - { { 16, 17 }, { 65, 0 }, { 245, 242 }, { 5, 195 }, { 1, 0 }, 2, 0, 0 }, - { { 33, 162 }, { 155, 1 }, { 177, 114 }, { 37, 8 }, { 1, 0 }, 14, 0, 0 }, - { { 161, 33 }, { 152, 0 }, { 127, 63 }, { 3, 7 }, { 1, 1 }, 0, 0, 0 }, - { { 161, 97 }, { 147, 0 }, { 193, 79 }, { 18, 5 }, { 0, 0 }, 10, 0, 0 }, - { { 33, 97 }, { 24, 0 }, { 193, 79 }, { 34, 5 }, { 0, 0 }, 12, 0, 0 }, - { { 49, 114 }, { 91, 131 }, { 244, 138 }, { 21, 5 }, { 0, 0 }, 0, 0, 0 }, - { { 161, 97 }, { 144, 0 }, { 116, 113 }, { 57, 103 }, { 0, 0 }, 0, 0, 0 }, - { { 113, 114 }, { 87, 0 }, { 84, 122 }, { 5, 5 }, { 0, 0 }, 12, 0, 0 }, - { { 144, 65 }, { 0, 0 }, { 84, 165 }, { 99, 69 }, { 0, 0 }, 8, 0, 0 }, - { { 33, 33 }, { 146, 1 }, { 133, 143 }, { 23, 9 }, { 0, 0 }, 12, 0, 0 }, - { { 33, 33 }, { 148, 5 }, { 117, 143 }, { 23, 9 }, { 0, 0 }, 12, 0, 0 }, - { { 33, 97 }, { 148, 0 }, { 118, 130 }, { 21, 55 }, { 0, 0 }, 12, 0, 0 }, - { { 49, 33 }, { 67, 0 }, { 158, 98 }, { 23, 44 }, { 1, 1 }, 2, 0, 0 }, - { { 33, 33 }, { 155, 0 }, { 97, 127 }, { 106, 10 }, { 0, 0 }, 2, 0, 0 }, - { { 97, 34 }, { 138, 6 }, { 117, 116 }, { 31, 15 }, { 0, 0 }, 8, 0, 0 }, - { { 161, 33 }, { 134, 13 }, { 114, 113 }, { 85, 24 }, { 1, 0 }, 0, 0, 0 }, - { { 33, 33 }, { 77, 0 }, { 84, 166 }, { 60, 28 }, { 0, 0 }, 8, 0, 0 }, - { { 49, 97 }, { 143, 0 }, { 147, 114 }, { 2, 11 }, { 1, 0 }, 8, 0, 0 }, - { { 49, 97 }, { 142, 0 }, { 147, 114 }, { 3, 9 }, { 1, 0 }, 8, 0, 0 }, - { { 49, 97 }, { 145, 0 }, { 147, 130 }, { 3, 9 }, { 1, 0 }, 10, 0, 0 }, - { { 49, 97 }, { 142, 0 }, { 147, 114 }, { 15, 15 }, { 1, 0 }, 10, 0, 0 }, - { { 33, 33 }, { 75, 0 }, { 170, 143 }, { 22, 10 }, { 1, 0 }, 8, 0, 0 }, - { { 49, 33 }, { 144, 0 }, { 126, 139 }, { 23, 12 }, { 1, 1 }, 6, 0, 0 }, - { { 49, 50 }, { 129, 0 }, { 117, 97 }, { 25, 25 }, { 1, 0 }, 0, 0, 0 }, - { { 50, 33 }, { 144, 0 }, { 155, 114 }, { 33, 23 }, { 0, 0 }, 4, 0, 0 }, - { { 225, 225 }, { 31, 0 }, { 133, 101 }, { 95, 26 }, { 0, 0 }, 0, 0, 0 }, - { { 225, 225 }, { 70, 0 }, { 136, 101 }, { 95, 26 }, { 0, 0 }, 0, 0, 0 }, - { { 161, 33 }, { 156, 0 }, { 117, 117 }, { 31, 10 }, { 0, 0 }, 2, 0, 0 }, - { { 49, 33 }, { 139, 0 }, { 132, 101 }, { 88, 26 }, { 0, 0 }, 0, 0, 0 }, - { { 225, 161 }, { 76, 0 }, { 102, 101 }, { 86, 38 }, { 0, 0 }, 0, 0, 0 }, - { { 98, 161 }, { 203, 0 }, { 118, 85 }, { 70, 54 }, { 0, 0 }, 0, 0, 0 }, - { { 98, 161 }, { 153, 0 }, { 87, 86 }, { 7, 7 }, { 0, 0 }, 11, 0, 0 }, - { { 98, 161 }, { 147, 0 }, { 119, 118 }, { 7, 7 }, { 0, 0 }, 11, 0, 0 }, - { { 34, 33 }, { 89, 0 }, { 255, 255 }, { 3, 15 }, { 2, 0 }, 0, 0, 0 }, - { { 33, 33 }, { 14, 0 }, { 255, 255 }, { 15, 15 }, { 1, 1 }, 0, 0, 0 }, - { { 34, 33 }, { 70, 128 }, { 134, 100 }, { 85, 24 }, { 0, 0 }, 0, 0, 0 }, - { { 33, 161 }, { 69, 0 }, { 102, 150 }, { 18, 10 }, { 0, 0 }, 0, 0, 0 }, - { { 33, 34 }, { 139, 0 }, { 146, 145 }, { 42, 42 }, { 1, 0 }, 0, 0, 0 }, - { { 162, 97 }, { 158, 64 }, { 223, 111 }, { 5, 7 }, { 0, 0 }, 2, 0, 0 }, - { { 32, 96 }, { 26, 0 }, { 239, 143 }, { 1, 6 }, { 0, 2 }, 0, 0, 0 }, - { { 33, 33 }, { 143, 128 }, { 241, 244 }, { 41, 9 }, { 0, 0 }, 10, 0, 0 }, - { { 119, 161 }, { 165, 0 }, { 83, 160 }, { 148, 5 }, { 0, 0 }, 2, 0, 0 }, - { { 97, 177 }, { 31, 128 }, { 168, 37 }, { 17, 3 }, { 0, 0 }, 10, 0, 0 }, - { { 97, 97 }, { 23, 0 }, { 145, 85 }, { 52, 22 }, { 0, 0 }, 12, 0, 0 }, - { { 113, 114 }, { 93, 0 }, { 84, 106 }, { 1, 3 }, { 0, 0 }, 0, 0, 0 }, - { { 33, 162 }, { 151, 0 }, { 33, 66 }, { 67, 53 }, { 0, 0 }, 8, 0, 0 }, - { { 161, 33 }, { 28, 0 }, { 161, 49 }, { 119, 71 }, { 1, 1 }, 0, 0, 0 }, - { { 33, 97 }, { 137, 3 }, { 17, 66 }, { 51, 37 }, { 0, 0 }, 10, 0, 0 }, - { { 161, 33 }, { 21, 0 }, { 17, 207 }, { 71, 7 }, { 1, 0 }, 0, 0, 0 }, - { { 58, 81 }, { 206, 0 }, { 248, 134 }, { 246, 2 }, { 0, 0 }, 2, 0, 0 }, - { { 33, 33 }, { 21, 0 }, { 33, 65 }, { 35, 19 }, { 1, 0 }, 0, 0, 0 }, - { { 6, 1 }, { 91, 0 }, { 116, 165 }, { 149, 114 }, { 0, 0 }, 0, 0, 0 }, - { { 34, 97 }, { 146, 131 }, { 177, 242 }, { 129, 38 }, { 0, 0 }, 12, 0, 0 }, - { { 65, 66 }, { 77, 0 }, { 241, 242 }, { 81, 245 }, { 1, 0 }, 0, 0, 0 }, - { { 97, 163 }, { 148, 128 }, { 17, 17 }, { 81, 19 }, { 1, 0 }, 6, 0, 0 }, - { { 97, 161 }, { 140, 128 }, { 17, 29 }, { 49, 3 }, { 0, 0 }, 6, 0, 0 }, - { { 164, 97 }, { 76, 0 }, { 243, 129 }, { 115, 35 }, { 1, 0 }, 4, 0, 0 }, - { { 2, 7 }, { 133, 3 }, { 210, 242 }, { 83, 246 }, { 0, 1 }, 0, 0, 0 }, - { { 17, 19 }, { 12, 128 }, { 163, 162 }, { 17, 229 }, { 1, 0 }, 0, 0, 0 }, - { { 17, 17 }, { 6, 0 }, { 246, 242 }, { 65, 230 }, { 1, 2 }, 4, 0, 0 }, - { { 147, 145 }, { 145, 0 }, { 212, 235 }, { 50, 17 }, { 0, 1 }, 8, 0, 0 }, - { { 4, 1 }, { 79, 0 }, { 250, 194 }, { 86, 5 }, { 0, 0 }, 12, 0, 0 }, - { { 33, 34 }, { 73, 0 }, { 124, 111 }, { 32, 12 }, { 0, 1 }, 6, 0, 0 }, - { { 49, 33 }, { 133, 0 }, { 221, 86 }, { 51, 22 }, { 1, 0 }, 10, 0, 0 }, - { { 32, 33 }, { 4, 129 }, { 218, 143 }, { 5, 11 }, { 2, 0 }, 6, 0, 0 }, - { { 5, 3 }, { 106, 128 }, { 241, 195 }, { 229, 229 }, { 0, 0 }, 6, 0, 0 }, - { { 7, 2 }, { 21, 0 }, { 236, 248 }, { 38, 22 }, { 0, 0 }, 10, 0, 0 }, - { { 5, 1 }, { 157, 0 }, { 103, 223 }, { 53, 5 }, { 0, 0 }, 8, 0, 0 }, - { { 24, 18 }, { 150, 0 }, { 250, 248 }, { 40, 229 }, { 0, 0 }, 10, 0, 0 }, - { { 16, 0 }, { 134, 3 }, { 168, 250 }, { 7, 3 }, { 0, 0 }, 6, 0, 0 }, - { { 17, 16 }, { 65, 3 }, { 248, 243 }, { 71, 3 }, { 2, 0 }, 4, 0, 0 }, - { { 1, 16 }, { 142, 0 }, { 241, 243 }, { 6, 2 }, { 2, 0 }, 14, 0, 0 }, - { { 14, 192 }, { 0, 0 }, { 31, 31 }, { 0, 255 }, { 0, 3 }, 14, 0, 0 }, - { { 6, 3 }, { 128, 136 }, { 248, 86 }, { 36, 132 }, { 0, 2 }, 14, 0, 0 }, - { { 14, 208 }, { 0, 5 }, { 248, 52 }, { 0, 4 }, { 0, 3 }, 14, 0, 0 }, - { { 14, 192 }, { 0, 0 }, { 246, 31 }, { 0, 2 }, { 0, 3 }, 14, 0, 0 }, - { { 213, 218 }, { 149, 64 }, { 55, 86 }, { 163, 55 }, { 0, 0 }, 0, 0, 0 }, - { { 53, 20 }, { 92, 8 }, { 178, 244 }, { 97, 21 }, { 2, 0 }, 10, 0, 0 }, - { { 14, 208 }, { 0, 0 }, { 246, 79 }, { 0, 245 }, { 0, 3 }, 14, 0, 0 }, - { { 38, 228 }, { 0, 0 }, { 255, 18 }, { 1, 22 }, { 0, 1 }, 14, 0, 0 }, - { { 0, 0 }, { 0, 0 }, { 243, 246 }, { 240, 201 }, { 0, 2 }, 14, 0, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 0, 0 }, { 0, 0 }, { 252, 250 }, { 5, 23 }, { 2, 0 }, 14, 52, 0 }, - { { 0, 1 }, { 2, 0 }, { 255, 255 }, { 7, 8 }, { 0, 0 }, 0, 48, 0 }, - { { 0, 0 }, { 0, 0 }, { 252, 250 }, { 5, 23 }, { 2, 0 }, 14, 58, 0 }, - { { 0, 0 }, { 0, 0 }, { 246, 246 }, { 12, 6 }, { 0, 0 }, 4, 60, 0 }, - { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 47, 0 }, - { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43, 0 }, - { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 49, 0 }, - { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43, 0 }, - { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 51, 0 }, - { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43, 0 }, - { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 54, 0 }, - { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 57, 0 }, - { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 72, 0 }, - { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 60, 0 }, - { { 14, 208 }, { 0, 10 }, { 245, 159 }, { 48, 2 }, { 0, 0 }, 14, 76, 0 }, - { { 14, 7 }, { 10, 93 }, { 228, 245 }, { 228, 229 }, { 3, 1 }, 6, 84, 0 }, - { { 2, 5 }, { 3, 10 }, { 180, 151 }, { 4, 247 }, { 0, 0 }, 14, 36, 0 }, - { { 78, 158 }, { 0, 0 }, { 246, 159 }, { 0, 2 }, { 0, 3 }, 14, 76, 0 }, - { { 17, 16 }, { 69, 8 }, { 248, 243 }, { 55, 5 }, { 2, 0 }, 8, 84, 0 }, - { { 14, 208 }, { 0, 0 }, { 246, 159 }, { 0, 2 }, { 0, 3 }, 14, 83, 0 }, - { { 128, 16 }, { 0, 13 }, { 255, 255 }, { 3, 20 }, { 3, 0 }, 12, 84, 0 }, - { { 14, 7 }, { 8, 81 }, { 248, 244 }, { 66, 228 }, { 0, 3 }, 14, 24, 0 }, - { { 14, 208 }, { 0, 10 }, { 245, 159 }, { 48, 2 }, { 0, 0 }, 14, 77, 0 }, - { { 1, 2 }, { 0, 0 }, { 250, 200 }, { 191, 151 }, { 0, 0 }, 7, 60, 0 }, - { { 1, 1 }, { 81, 0 }, { 250, 250 }, { 135, 183 }, { 0, 0 }, 6, 65, 0 }, - { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 59, 0 }, - { { 1, 2 }, { 89, 0 }, { 250, 248 }, { 136, 182 }, { 0, 0 }, 6, 51, 0 }, - { { 1, 0 }, { 0, 0 }, { 249, 250 }, { 10, 6 }, { 3, 0 }, 14, 45, 0 }, - { { 0, 0 }, { 128, 0 }, { 249, 246 }, { 137, 108 }, { 3, 0 }, 14, 71, 0 }, - { { 3, 12 }, { 128, 8 }, { 248, 246 }, { 136, 182 }, { 3, 0 }, 15, 60, 0 }, - { { 3, 12 }, { 133, 0 }, { 248, 246 }, { 136, 182 }, { 3, 0 }, 15, 58, 0 }, - { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 53, 0 }, - { { 14, 3 }, { 64, 0 }, { 200, 155 }, { 73, 105 }, { 0, 2 }, 14, 64, 0 }, - { { 215, 199 }, { 220, 0 }, { 173, 141 }, { 5, 5 }, { 3, 0 }, 14, 71, 0 }, - { { 215, 199 }, { 220, 0 }, { 168, 136 }, { 4, 4 }, { 3, 0 }, 14, 61, 0 }, - { { 128, 17 }, { 0, 0 }, { 246, 103 }, { 6, 23 }, { 3, 3 }, 14, 61, 0 }, - { { 128, 17 }, { 0, 9 }, { 245, 70 }, { 5, 22 }, { 2, 3 }, 14, 48, 0 }, - { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 48, 0 }, - { { 6, 18 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 3, 0 }, 0, 69, 0 }, - { { 6, 18 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 68, 0 }, - { { 1, 2 }, { 88, 0 }, { 103, 117 }, { 231, 7 }, { 0, 0 }, 0, 63, 0 }, - { { 65, 66 }, { 69, 8 }, { 248, 117 }, { 72, 5 }, { 0, 0 }, 0, 74, 0 }, - { { 10, 30 }, { 64, 78 }, { 224, 255 }, { 240, 5 }, { 3, 0 }, 8, 60, 0 }, - { { 10, 30 }, { 124, 82 }, { 224, 255 }, { 240, 2 }, { 3, 0 }, 8, 80, 0 }, - { { 14, 0 }, { 64, 8 }, { 122, 123 }, { 74, 27 }, { 0, 2 }, 14, 64, 0 }, - { { 14, 7 }, { 10, 64 }, { 228, 85 }, { 228, 57 }, { 3, 1 }, 6, 69, 0 }, - { { 5, 4 }, { 5, 64 }, { 249, 214 }, { 50, 165 }, { 3, 0 }, 14, 73, 0 }, - { { 2, 21 }, { 63, 0 }, { 0, 247 }, { 243, 245 }, { 3, 0 }, 8, 75, 0 }, - { { 1, 2 }, { 79, 0 }, { 250, 248 }, { 141, 181 }, { 0, 0 }, 7, 68, 0 }, - { { 0, 0 }, { 0, 0 }, { 246, 246 }, { 12, 6 }, { 0, 0 }, 4, 48, 0 }, - { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 53, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 }, - { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35, 0 } - }; diff --git a/source/audiolib/src/ll.h b/source/audiolib/src/ll.h deleted file mode 100644 index a0a581ffe..000000000 --- a/source/audiolib/src/ll.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef __linklist_h -#define __linklist_h -#ifdef __cplusplus -extern "C" { -#endif - - -#define NewNode(type) ((type*)SafeMalloc(sizeof(type))) - - -#define LL_CreateNewLinkedList(rootnode,type,next,prev) \ - { \ - (rootnode) = NewNode(type); \ - (rootnode)->prev = (rootnode); \ - (rootnode)->next = (rootnode); \ - } - - - -#define LL_AddNode(rootnode, newnode, next, prev) \ - { \ - (newnode)->next = (rootnode); \ - (newnode)->prev = (rootnode)->prev; \ - (rootnode)->prev->next = (newnode); \ - (rootnode)->prev = (newnode); \ - } - -#define LL_TransferList(oldroot,newroot,next,prev) \ - { \ - if ((oldroot)->prev != (oldroot)) \ - { \ - (oldroot)->prev->next = (newroot); \ - (oldroot)->next->prev = (newroot)->prev; \ - (newroot)->prev->next = (oldroot)->next; \ - (newroot)->prev = (oldroot)->prev; \ - (oldroot)->next = (oldroot); \ - (oldroot)->prev = (oldroot); \ - } \ - } - -#define LL_ReverseList(root,type,next,prev) \ - { \ - type *newend,*trav,*tprev; \ - \ - newend = (root)->next; \ - for(trav = (root)->prev; trav != newend; trav = tprev) \ - { \ - tprev = trav->prev; \ - LL_MoveNode(trav,newend,next,prev); \ - } \ - } - - -#define LL_RemoveNode(node,next,prev) \ - { \ - (node)->prev->next = (node)->next; \ - (node)->next->prev = (node)->prev; \ - (node)->next = (node); \ - (node)->prev = (node); \ - } - - -#define LL_SortedInsertion(rootnode,insertnode,next,prev,type,sortparm) \ - { \ - type *hoya; \ - \ - hoya = (rootnode)->next; \ - while((hoya != (rootnode)) && ((insertnode)->sortparm > hoya->sortparm)) \ - { \ - hoya = hoya->next; \ - } \ - LL_AddNode(hoya,(insertnode),next,prev); \ - } - -#define LL_MoveNode(node,newroot,next,prev) \ - { \ - LL_RemoveNode((node),next,prev); \ - LL_AddNode((newroot),(node),next,prev); \ - } - -#define LL_ListEmpty(list,next,prev) \ - ( \ - ((list)->next == (list)) && \ - ((list)->prev == (list)) \ - ) - -#define LL_Free(list) SafeFree(list) -#define LL_Reset(list,next,prev) (list)->next = (list)->prev = (list) -#define LL_New LL_CreateNewLinkedList -#define LL_Remove LL_RemoveNode -#define LL_Add LL_AddNode -#define LL_Empty LL_ListEmpty -#define LL_Move LL_MoveNode - - -#ifdef __cplusplus -}; -#endif -#endif diff --git a/source/audiolib/src/midi.cpp b/source/audiolib/src/midi.cpp deleted file mode 100644 index cef907974..000000000 --- a/source/audiolib/src/midi.cpp +++ /dev/null @@ -1,1023 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2010-2019 EDuke32 developers and contributors -Copyright (C) 2019 Nuke.YKT - -This file is part of NBlood. - -NBlood is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- - -/********************************************************************** - module: MIDI.C - - author: James R. Dose - date: May 25, 1994 - - Midi song file playback routines. - - (c) Copyright 1994 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#include "midi.h" - -#include "_midi.h" -#include "_multivc.h" -#include "compat.h" -#include "multivoc.h" -#include "music.h" -#include "pragmas.h" -#include "sndcards.h" -#include "driver_adlib.h" -#include "c_cvars.h" - -CUSTOM_CVARD(Int, mus_emidicard, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "force a specific EMIDI instrument set") -{ - ASS_EMIDICard = clamp(*self, -1, 10); -} - - -extern int MV_MixRate; -extern int ASS_MIDISoundDriver; - -int MIDI_GetDevice() -{ - return ASS_MIDISoundDriver; -} - -static const int _MIDI_CommandLengths[NUM_MIDI_CHANNELS] = { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0 }; - -static track * _MIDI_TrackPtr; -static int _MIDI_TrackMemSize; -static int _MIDI_NumTracks; - -static int _MIDI_SongActive; -static int _MIDI_SongLoaded; -static int _MIDI_Loop; - -static int _MIDI_Division; -static int _MIDI_Tick; -static int _MIDI_Beat = 1; -static int _MIDI_Measure = 1; -static uint32_t _MIDI_Time; -static int _MIDI_BeatsPerMeasure; -static int _MIDI_TicksPerBeat; -static int _MIDI_TimeBase; -static int _MIDI_FPSecondsPerTick; -static uint32_t _MIDI_TotalTime; -static int _MIDI_TotalTicks; -static int _MIDI_TotalBeats; -static int _MIDI_TotalMeasures; - -uint32_t _MIDI_PositionInTicks; -uint32_t _MIDI_GlobalPositionInTicks; - -static int _MIDI_Context; - -static int _MIDI_ActiveTracks; -static int _MIDI_TotalVolume = MIDI_MaxVolume; - -static int _MIDI_ChannelVolume[ NUM_MIDI_CHANNELS ]; - -static midifuncs *_MIDI_Funcs; - -static int _MIDI_Reset; - -int MV_MIDIRenderTempo = -1; -int MV_MIDIRenderTimer; - -static char *_MIDI_SongPtr; - -void MIDI_Restart(void) -{ - MIDI_PlaySong(_MIDI_SongPtr, _MIDI_Loop); -} - -static int _MIDI_ReadNumber(void *from, size_t size) -{ - if (size > 4) - size = 4; - - char *FromPtr = (char *)from; - int value = 0; - - while (size--) - { - value <<= 8; - value += *FromPtr++; - } - - return value; -} - -static int _MIDI_ReadDelta(track *ptr) -{ - int value; - - GET_NEXT_EVENT(ptr, value); - - if (value & 0x80) - { - value &= 0x7f; - char c; - - do - { - GET_NEXT_EVENT(ptr, c); - value = (value << 7) + (c & 0x7f); - } - while (c & 0x80); - } - - return value; -} - -static void _MIDI_ResetTracks(void) -{ - _MIDI_Tick = 0; - _MIDI_Beat = 1; - _MIDI_Measure = 1; - _MIDI_Time = 0; - _MIDI_BeatsPerMeasure = 4; - _MIDI_TicksPerBeat = _MIDI_Division; - _MIDI_TimeBase = 4; - _MIDI_PositionInTicks = 0; - _MIDI_ActiveTracks = 0; - _MIDI_Context = 0; - - track *ptr = _MIDI_TrackPtr; - for (bssize_t i = 0; i < _MIDI_NumTracks; ++i) - { - ptr->pos = ptr->start; - ptr->delay = _MIDI_ReadDelta(ptr); - ptr->active = ptr->EMIDI_IncludeTrack; - ptr->RunningStatus = 0; - ptr->currentcontext = 0; - ptr->context[ 0 ].loopstart = ptr->start; - ptr->context[ 0 ].loopcount = 0; - - if (ptr->active) - _MIDI_ActiveTracks++; - - ptr++; - } -} - -static void _MIDI_AdvanceTick(void) -{ - _MIDI_PositionInTicks++; - _MIDI_Time += _MIDI_FPSecondsPerTick; - - _MIDI_Tick++; - while (_MIDI_Tick > _MIDI_TicksPerBeat) - { - _MIDI_Tick -= _MIDI_TicksPerBeat; - _MIDI_Beat++; - } - while (_MIDI_Beat > _MIDI_BeatsPerMeasure) - { - _MIDI_Beat -= _MIDI_BeatsPerMeasure; - _MIDI_Measure++; - } -} - -static void _MIDI_SysEx(track *Track) -{ - int length = _MIDI_ReadDelta(Track); - Track->pos += length; -} - - -static void _MIDI_MetaEvent(track *Track) -{ - int command; - int length; - - GET_NEXT_EVENT(Track, command); - GET_NEXT_EVENT(Track, length); - - switch (command) - { - case MIDI_END_OF_TRACK: - Track->active = FALSE; - - _MIDI_ActiveTracks--; - break; - - case MIDI_TEMPO_CHANGE: - { - int tempo = tabledivide32_noinline(60000000L, _MIDI_ReadNumber(Track->pos, 3)); - MIDI_SetTempo(tempo); - break; - } - - case MIDI_TIME_SIGNATURE: - { - if ((_MIDI_Tick > 0) || (_MIDI_Beat > 1)) - _MIDI_Measure++; - - _MIDI_Tick = 0; - _MIDI_Beat = 1; - _MIDI_TimeBase = 1; - _MIDI_BeatsPerMeasure = (int)*Track->pos; - int denominator = (int) * (Track->pos + 1); - - while (denominator > 0) - { - _MIDI_TimeBase += _MIDI_TimeBase; - denominator--; - } - - _MIDI_TicksPerBeat = tabledivide32_noinline(_MIDI_Division * 4, _MIDI_TimeBase); - break; - } - } - - Track->pos += length; -} - -static int _MIDI_InterpretControllerInfo(track *Track, int TimeSet, int channel, int c1, int c2) -{ - track *trackptr; - int tracknum; - int loopcount; - - switch (c1) - { - case MIDI_MONO_MODE_ON : - Track->pos++; - break; - - case MIDI_VOLUME : - if (!Track->EMIDI_VolumeChange) - _MIDI_SetChannelVolume(channel, c2); - break; - - case EMIDI_INCLUDE_TRACK : - case EMIDI_EXCLUDE_TRACK : - break; - - case EMIDI_PROGRAM_CHANGE : - if (Track->EMIDI_ProgramChange) - _MIDI_Funcs->ProgramChange(channel, c2 & 0x7f); - break; - - case EMIDI_VOLUME_CHANGE : - if (Track->EMIDI_VolumeChange) - _MIDI_SetChannelVolume(channel, c2); - break; - - case EMIDI_CONTEXT_START : - break; - - case EMIDI_CONTEXT_END : - if ((Track->currentcontext == _MIDI_Context) || (_MIDI_Context < 0) || - (Track->context[_MIDI_Context].pos == nullptr)) - break; - - Track->currentcontext = _MIDI_Context; - Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart; - Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount; - Track->pos = Track->context[ _MIDI_Context ].pos; - Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus; - - if (TimeSet) - { - break; - } - - _MIDI_Time = Track->context[ _MIDI_Context ].time; - _MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick; - _MIDI_Tick = Track->context[ _MIDI_Context ].tick; - _MIDI_Beat = Track->context[ _MIDI_Context ].beat; - _MIDI_Measure = Track->context[ _MIDI_Context ].measure; - _MIDI_BeatsPerMeasure = Track->context[ _MIDI_Context ].BeatsPerMeasure; - _MIDI_TicksPerBeat = Track->context[ _MIDI_Context ].TicksPerBeat; - _MIDI_TimeBase = Track->context[ _MIDI_Context ].TimeBase; - TimeSet = TRUE; - break; - - case EMIDI_LOOP_START : - case EMIDI_SONG_LOOP_START : - loopcount = (c2 == 0) ? EMIDI_INFINITE : c2; - - if (c1 == EMIDI_SONG_LOOP_START) - { - trackptr = _MIDI_TrackPtr; - tracknum = _MIDI_NumTracks; - } - else - { - trackptr = Track; - tracknum = 1; - } - - while (tracknum > 0) - { - trackptr->context[ 0 ].loopcount = loopcount; - trackptr->context[ 0 ].pos = trackptr->pos; - trackptr->context[ 0 ].loopstart = trackptr->pos; - trackptr->context[ 0 ].RunningStatus = trackptr->RunningStatus; - trackptr->context[ 0 ].active = trackptr->active; - trackptr->context[ 0 ].delay = trackptr->delay; - trackptr->context[ 0 ].time = _MIDI_Time; - trackptr->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; - trackptr->context[ 0 ].tick = _MIDI_Tick; - trackptr->context[ 0 ].beat = _MIDI_Beat; - trackptr->context[ 0 ].measure = _MIDI_Measure; - trackptr->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; - trackptr->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat; - trackptr->context[ 0 ].TimeBase = _MIDI_TimeBase; - trackptr++; - tracknum--; - } - break; - - case EMIDI_LOOP_END : - case EMIDI_SONG_LOOP_END : - if ((c2 != EMIDI_END_LOOP_VALUE) || (Track->context[0].loopstart == nullptr) || (Track->context[0].loopcount == 0)) - break; - - if (c1 == EMIDI_SONG_LOOP_END) - { - trackptr = _MIDI_TrackPtr; - tracknum = _MIDI_NumTracks; - _MIDI_ActiveTracks = 0; - } - else - { - trackptr = Track; - tracknum = 1; - _MIDI_ActiveTracks--; - } - - while (tracknum > 0) - { - if (trackptr->context[ 0 ].loopcount != EMIDI_INFINITE) - { - trackptr->context[ 0 ].loopcount--; - } - - trackptr->pos = trackptr->context[ 0 ].loopstart; - trackptr->RunningStatus = trackptr->context[ 0 ].RunningStatus; - trackptr->delay = trackptr->context[ 0 ].delay; - trackptr->active = trackptr->context[ 0 ].active; - if (trackptr->active) - { - _MIDI_ActiveTracks++; - } - - if (!TimeSet) - { - _MIDI_Time = trackptr->context[ 0 ].time; - _MIDI_FPSecondsPerTick = trackptr->context[ 0 ].FPSecondsPerTick; - _MIDI_Tick = trackptr->context[ 0 ].tick; - _MIDI_Beat = trackptr->context[ 0 ].beat; - _MIDI_Measure = trackptr->context[ 0 ].measure; - _MIDI_BeatsPerMeasure = trackptr->context[ 0 ].BeatsPerMeasure; - _MIDI_TicksPerBeat = trackptr->context[ 0 ].TicksPerBeat; - _MIDI_TimeBase = trackptr->context[ 0 ].TimeBase; - TimeSet = TRUE; - } - - trackptr++; - tracknum--; - } - break; - - default : - if (_MIDI_Funcs->ControlChange) - _MIDI_Funcs->ControlChange(channel, c1, c2); - } - - return TimeSet; -} - -static void _MIDI_ServiceRoutine(void) -{ - if (!_MIDI_SongActive) - return; - - track *Track = _MIDI_TrackPtr; - int tracknum = 0; - int TimeSet = FALSE; - int c1 = 0; - int c2 = 0; - - while (tracknum < _MIDI_NumTracks) - { - while ((Track->active) && (Track->delay == 0)) - { - int event; - GET_NEXT_EVENT(Track, event); - - if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) - { - switch (event) - { - case MIDI_SYSEX: - case MIDI_SYSEX_CONTINUE: _MIDI_SysEx(Track); break; - case MIDI_META_EVENT: _MIDI_MetaEvent(Track); break; - } - - if (Track->active) - Track->delay = _MIDI_ReadDelta(Track); - continue; - } - - if (event & MIDI_RUNNING_STATUS) - Track->RunningStatus = event; - else - { - event = Track->RunningStatus; - Track->pos--; - } - - int const channel = GET_MIDI_CHANNEL(event); - int const command = GET_MIDI_COMMAND(event); - - if (_MIDI_CommandLengths[ command ] > 0) - { - GET_NEXT_EVENT(Track, c1); - if (_MIDI_CommandLengths[ command ] > 1) - GET_NEXT_EVENT(Track, c2); - } - - switch (command) - { - case MIDI_NOTE_OFF: - if (_MIDI_Funcs->NoteOff) - _MIDI_Funcs->NoteOff(channel, c1, c2); - break; - - case MIDI_NOTE_ON: - if (_MIDI_Funcs->NoteOn) - _MIDI_Funcs->NoteOn(channel, c1, c2); - break; - - case MIDI_POLY_AFTER_TCH: - if (_MIDI_Funcs->PolyAftertouch) - _MIDI_Funcs->PolyAftertouch(channel, c1, c2); - break; - - case MIDI_CONTROL_CHANGE: - TimeSet = _MIDI_InterpretControllerInfo(Track, TimeSet, channel, c1, c2); - break; - - case MIDI_PROGRAM_CHANGE: - if ((_MIDI_Funcs->ProgramChange) && (!Track->EMIDI_ProgramChange)) - _MIDI_Funcs->ProgramChange(channel, c1 & 0x7f); - break; - - case MIDI_AFTER_TOUCH: - if (_MIDI_Funcs->ChannelAftertouch) - _MIDI_Funcs->ChannelAftertouch(channel, c1); - break; - - case MIDI_PITCH_BEND: - if (_MIDI_Funcs->PitchBend) - _MIDI_Funcs->PitchBend(channel, c1, c2); - break; - - default: break; - } - - Track->delay = _MIDI_ReadDelta(Track); - } - - Track->delay--; - Track++; - tracknum++; - - if (_MIDI_ActiveTracks == 0) - { - _MIDI_ResetTracks(); - if (_MIDI_Loop) - { - tracknum = 0; - Track = _MIDI_TrackPtr; - } - else - { - _MIDI_SongActive = FALSE; - break; - } - } - } - - _MIDI_AdvanceTick(); - _MIDI_GlobalPositionInTicks++; -} - -static void _MIDI_ServiceMultivoc(void) -{ - int16_t * buffer16 = (int16_t *)MV_MusicBuffer; - int const samples = MV_BufferSize >> 2; - - for (int i = 0; i < samples; i++) - { - Bit16s buf[2]; - while (MV_MIDIRenderTimer >= MV_MixRate) - { - if (MV_MIDIRenderTempo >= 0) - _MIDI_ServiceRoutine(); - MV_MIDIRenderTimer -= MV_MixRate; - } - if (MV_MIDIRenderTempo >= 0) MV_MIDIRenderTimer += MV_MIDIRenderTempo; - OPL3_GenerateResampled(AL_GetChip(), buf); - *buffer16++ = clamp(buf[0]<ControlChange == nullptr) - return MIDI_Error; - - _MIDI_Funcs->ControlChange(channel, c1, c2); - - return MIDI_Ok; -} - -static int _MIDI_SendProgramChange(int channel, int c1) -{ - if (_MIDI_Funcs == nullptr || _MIDI_Funcs->ProgramChange == nullptr) - return MIDI_Error; - - _MIDI_Funcs->ProgramChange(channel, c1); - - return MIDI_Ok; -} - -int MIDI_AllNotesOff(void) -{ - SoundDriver_MIDI_Lock(); - - for (bssize_t channel = 0; channel < NUM_MIDI_CHANNELS; channel++) - { - _MIDI_SendControlChange(channel, MIDI_HOLD1, 0); - _MIDI_SendControlChange(channel, MIDI_SOSTENUTO, 0); - _MIDI_SendControlChange(channel, MIDI_ALL_NOTES_OFF, 0); - _MIDI_SendControlChange(channel, MIDI_ALL_SOUNDS_OFF, 0); - } - - SoundDriver_MIDI_Unlock(); - - return MIDI_Ok; -} - -static void _MIDI_SetChannelVolume(int channel, int volume) -{ - _MIDI_ChannelVolume[channel] = volume; - - if (_MIDI_Funcs == nullptr || _MIDI_Funcs->ControlChange == nullptr) - return; - - volume *= _MIDI_TotalVolume; - volume = tabledivide32_noinline(volume, MIDI_MaxVolume); - - _MIDI_Funcs->ControlChange(channel, MIDI_VOLUME, volume); -} - -static void _MIDI_SendChannelVolumes(void) -{ - for (bssize_t channel = 0; channel < NUM_MIDI_CHANNELS; channel++) - _MIDI_SetChannelVolume(channel, _MIDI_ChannelVolume[channel]); -} - -int MIDI_Reset(void) -{ - MIDI_AllNotesOff(); - - SoundDriver_MIDI_Lock(); - - for (bssize_t channel = 0; channel < NUM_MIDI_CHANNELS; channel++) - { - _MIDI_SendControlChange(channel, MIDI_RESET_ALL_CONTROLLERS, 0); - _MIDI_SendControlChange(channel, MIDI_RPN_MSB, MIDI_PITCHBEND_MSB); - _MIDI_SendControlChange(channel, MIDI_RPN_LSB, MIDI_PITCHBEND_LSB); - _MIDI_SendControlChange(channel, MIDI_DATAENTRY_MSB, 2); /* Pitch Bend Sensitivity MSB */ - _MIDI_SendControlChange(channel, MIDI_DATAENTRY_LSB, 0); /* Pitch Bend Sensitivity LSB */ - _MIDI_ChannelVolume[channel] = GENMIDI_DefaultVolume; - _MIDI_SendControlChange(channel, MIDI_PAN, 64); // begin TURRICAN's recommendation - _MIDI_SendControlChange(channel, MIDI_REVERB, 40); - _MIDI_SendControlChange(channel, MIDI_CHORUS, 0); - _MIDI_SendControlChange(channel, MIDI_BANK_SELECT_MSB, 0); - _MIDI_SendControlChange(channel, MIDI_BANK_SELECT_LSB, 0); - _MIDI_SendProgramChange(channel, 0); // end TURRICAN's recommendation - } - - _MIDI_SendChannelVolumes(); - - SoundDriver_MIDI_Unlock(); - - _MIDI_Reset = TRUE; - - return MIDI_Ok; -} - - -int MIDI_SetVolume(int volume) -{ - if (_MIDI_Funcs == nullptr) - return MIDI_NullMidiModule; - - volume = min(MIDI_MaxVolume, volume); - volume = max(0, volume); - - _MIDI_TotalVolume = volume; - - SoundDriver_MIDI_Lock(); - - if (_MIDI_Funcs->SetVolume) - _MIDI_Funcs->SetVolume(volume); - else - _MIDI_SendChannelVolumes(); - - SoundDriver_MIDI_Unlock(); - - return MIDI_Ok; -} - - -int MIDI_GetVolume(void) -{ - if (_MIDI_Funcs == nullptr) - return MIDI_NullMidiModule; - - SoundDriver_MIDI_Lock(); - int volume = (_MIDI_Funcs->GetVolume) ? _MIDI_Funcs->GetVolume() : _MIDI_TotalVolume; - SoundDriver_MIDI_Unlock(); - - return volume; -} - -void MIDI_SetLoopFlag(int loopflag) { _MIDI_Loop = loopflag; } - -void MIDI_ContinueSong(void) -{ - if (!_MIDI_SongLoaded) - return; - - _MIDI_SongActive = TRUE; -} - -void MIDI_PauseSong(void) -{ - if (!_MIDI_SongLoaded) - return; - - _MIDI_SongActive = FALSE; - MIDI_AllNotesOff(); -} - -void MIDI_SetMidiFuncs(midifuncs *funcs) { _MIDI_Funcs = funcs; } - -void MIDI_StopSong(void) -{ - if (!_MIDI_SongLoaded) - return; - - SoundDriver_MIDI_HaltPlayback(); - - _MIDI_SongActive = FALSE; - _MIDI_SongLoaded = FALSE; - - MIDI_Reset(); - _MIDI_ResetTracks(); - - DO_FREE_AND_NULL(_MIDI_TrackPtr); - - _MIDI_NumTracks = 0; - _MIDI_TrackMemSize = 0; - - _MIDI_TotalTime = 0; - _MIDI_TotalTicks = 0; - _MIDI_TotalBeats = 0; - _MIDI_TotalMeasures = 0; -} - -int MIDI_PlaySong(char *song, int loopflag) -{ - if (_MIDI_Funcs == nullptr) - return MIDI_NullMidiModule; - - if (B_UNBUF32(song) != MIDI_HEADER_SIGNATURE) - return MIDI_InvalidMidiFile; - - _MIDI_SongPtr = song; - - song += 4; - int const headersize = _MIDI_ReadNumber(song, 4); - song += 4; - int const format = _MIDI_ReadNumber(song, 2); - - int My_MIDI_NumTracks = _MIDI_ReadNumber(song + 2, 2); - int My_MIDI_Division = _MIDI_ReadNumber(song + 4, 2); - - if (My_MIDI_Division < 0) - { - // If a SMPTE time division is given, just set to 96 so no errors occur - My_MIDI_Division = 96; - } - - if (format > MAX_FORMAT) - return MIDI_UnknownMidiFormat; - - char *ptr = song + headersize; - - if (My_MIDI_NumTracks == 0) - return MIDI_NoTracks; - - int My_MIDI_TrackMemSize = My_MIDI_NumTracks * sizeof(track); - track * My_MIDI_TrackPtr = (track *)Xmalloc(My_MIDI_TrackMemSize); - - auto CurrentTrack = My_MIDI_TrackPtr; - int numtracks = My_MIDI_NumTracks; - - while (numtracks--) - { - if (B_UNBUF32(ptr) != MIDI_TRACK_SIGNATURE) - { - DO_FREE_AND_NULL(My_MIDI_TrackPtr); - - My_MIDI_TrackMemSize = 0; - - return MIDI_InvalidTrack; - } - - int tracklength = _MIDI_ReadNumber(ptr + 4, 4); - ptr += 8; - CurrentTrack->start = ptr; - ptr += tracklength; - CurrentTrack++; - } - - // at this point we know song load is successful - - if (_MIDI_SongLoaded) - MIDI_StopSong(); - - _MIDI_Loop = loopflag; - _MIDI_NumTracks = My_MIDI_NumTracks; - _MIDI_Division = My_MIDI_Division; - _MIDI_TrackMemSize = My_MIDI_TrackMemSize; - _MIDI_TrackPtr = My_MIDI_TrackPtr; - - _MIDI_InitEMIDI(); - _MIDI_ResetTracks(); - - if (!_MIDI_Reset) - MIDI_Reset(); - - _MIDI_Reset = FALSE; - - // this can either stay like this, or I can add another field to the MIDI driver spec that holds the service callback - if (SoundDriver_MIDI_StartPlayback(ASS_MIDISoundDriver == ASS_OPL3 ? _MIDI_ServiceMultivoc : _MIDI_ServiceRoutine) != MIDI_Ok) - return MIDI_DriverError; - - MIDI_SetTempo(120); - - _MIDI_SongLoaded = TRUE; - _MIDI_SongActive = TRUE; - - return MIDI_Ok; -} - -void MIDI_SetTempo(int tempo) -{ - SoundDriver_MIDI_SetTempo(tempo, _MIDI_Division); - int const tickspersecond = tempo * _MIDI_Division / 60; - _MIDI_FPSecondsPerTick = tabledivide32_noinline(1 << TIME_PRECISION, tickspersecond); -} - -static void _MIDI_InitEMIDI(void) -{ - int type = EMIDI_GeneralMIDI; - - switch (ASS_MIDISoundDriver) - { - case ASS_OPL3: - type = EMIDI_SoundBlaster; - break; - } - - if (ASS_EMIDICard != -1) - type = ASS_EMIDICard; - - _MIDI_ResetTracks(); - - _MIDI_TotalTime = 0; - _MIDI_TotalTicks = 0; - _MIDI_TotalBeats = 0; - _MIDI_TotalMeasures = 0; - - track *Track = _MIDI_TrackPtr; - int tracknum = 0; - - while ((tracknum < _MIDI_NumTracks) && (Track != nullptr)) - { - _MIDI_Tick = 0; - _MIDI_Beat = 1; - _MIDI_Measure = 1; - _MIDI_Time = 0; - _MIDI_BeatsPerMeasure = 4; - _MIDI_TicksPerBeat = _MIDI_Division; - _MIDI_TimeBase = 4; - - _MIDI_PositionInTicks = 0; - _MIDI_ActiveTracks = 0; - _MIDI_Context = -1; - - Track->RunningStatus = 0; - Track->active = TRUE; - - Track->EMIDI_ProgramChange = FALSE; - Track->EMIDI_VolumeChange = FALSE; - Track->EMIDI_IncludeTrack = TRUE; - - memset(Track->context, 0, sizeof(Track->context)); - - while (Track->delay > 0) - { - _MIDI_AdvanceTick(); - Track->delay--; - } - - int IncludeFound = FALSE; - - while (Track->active) - { - int event; - - GET_NEXT_EVENT(Track, event); - - if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) - { - switch (event) - { - case MIDI_SYSEX: - case MIDI_SYSEX_CONTINUE: _MIDI_SysEx(Track); break; - case MIDI_META_EVENT: _MIDI_MetaEvent(Track); break; - } - - if (Track->active) - { - Track->delay = _MIDI_ReadDelta(Track); - while (Track->delay > 0) - { - _MIDI_AdvanceTick(); - Track->delay--; - } - } - - continue; - } - - if (event & MIDI_RUNNING_STATUS) - Track->RunningStatus = event; - else - { - event = Track->RunningStatus; - Track->pos--; - } - -// channel = GET_MIDI_CHANNEL(event); - int const command = GET_MIDI_COMMAND(event); - int length = _MIDI_CommandLengths[ command ]; - - if (command == MIDI_CONTROL_CHANGE) - { - if (*Track->pos == MIDI_MONO_MODE_ON) - length++; - - int c1, c2; - GET_NEXT_EVENT(Track, c1); - GET_NEXT_EVENT(Track, c2); - length -= 2; - - switch (c1) - { - case EMIDI_LOOP_START : - case EMIDI_SONG_LOOP_START : - Track->context[ 0 ].loopcount = (c2 == 0) ? EMIDI_INFINITE : c2; - Track->context[ 0 ].pos = Track->pos; - Track->context[ 0 ].loopstart = Track->pos; - Track->context[ 0 ].RunningStatus = Track->RunningStatus; - Track->context[ 0 ].time = _MIDI_Time; - Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; - Track->context[ 0 ].tick = _MIDI_Tick; - Track->context[ 0 ].beat = _MIDI_Beat; - Track->context[ 0 ].measure = _MIDI_Measure; - Track->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; - Track->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat; - Track->context[ 0 ].TimeBase = _MIDI_TimeBase; - break; - - case EMIDI_LOOP_END : - case EMIDI_SONG_LOOP_END : - if (c2 == EMIDI_END_LOOP_VALUE) - { - Track->context[ 0 ].loopstart = nullptr; - Track->context[ 0 ].loopcount = 0; - } - break; - - case EMIDI_INCLUDE_TRACK : - if (EMIDI_AffectsCurrentCard(c2, type)) - { - //printf( "Include track %d on card %d\n", tracknum, c2 ); - IncludeFound = TRUE; - Track->EMIDI_IncludeTrack = TRUE; - } - else if (!IncludeFound) - { - //printf( "Track excluded %d on card %d\n", tracknum, c2 ); - IncludeFound = TRUE; - Track->EMIDI_IncludeTrack = FALSE; - } - break; - - case EMIDI_EXCLUDE_TRACK : - if (EMIDI_AffectsCurrentCard(c2, type)) - { - //printf( "Exclude track %d on card %d\n", tracknum, c2 ); - Track->EMIDI_IncludeTrack = FALSE; - } - break; - - case EMIDI_PROGRAM_CHANGE : - if (!Track->EMIDI_ProgramChange) - //printf( "Program change on track %d\n", tracknum ); - Track->EMIDI_ProgramChange = TRUE; - break; - - case EMIDI_VOLUME_CHANGE : - if (!Track->EMIDI_VolumeChange) - //printf( "Volume change on track %d\n", tracknum ); - Track->EMIDI_VolumeChange = TRUE; - break; - - case EMIDI_CONTEXT_START : - if ((c2 > 0) && (c2 < EMIDI_NUM_CONTEXTS)) - { - Track->context[ c2 ].pos = Track->pos; - Track->context[ c2 ].loopstart = Track->context[ 0 ].loopstart; - Track->context[ c2 ].loopcount = Track->context[ 0 ].loopcount; - Track->context[ c2 ].RunningStatus = Track->RunningStatus; - Track->context[ c2 ].time = _MIDI_Time; - Track->context[ c2 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; - Track->context[ c2 ].tick = _MIDI_Tick; - Track->context[ c2 ].beat = _MIDI_Beat; - Track->context[ c2 ].measure = _MIDI_Measure; - Track->context[ c2 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; - Track->context[ c2 ].TicksPerBeat = _MIDI_TicksPerBeat; - Track->context[ c2 ].TimeBase = _MIDI_TimeBase; - } - break; - - case EMIDI_CONTEXT_END : - break; - } - } - - Track->pos += length; - Track->delay = _MIDI_ReadDelta(Track); - - while (Track->delay > 0) - { - _MIDI_AdvanceTick(); - Track->delay--; - } - } - - _MIDI_TotalTime = max(_MIDI_TotalTime, _MIDI_Time); - if (RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick) > - RELATIVE_BEAT(_MIDI_TotalMeasures, _MIDI_TotalBeats, _MIDI_TotalTicks)) - { - _MIDI_TotalTicks = _MIDI_Tick; - _MIDI_TotalBeats = _MIDI_Beat; - _MIDI_TotalMeasures = _MIDI_Measure; - } - - Track++; - tracknum++; - } - - _MIDI_ResetTracks(); -} - diff --git a/source/audiolib/src/midi.h b/source/audiolib/src/midi.h deleted file mode 100644 index fee2257f5..000000000 --- a/source/audiolib/src/midi.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -/********************************************************************** - module: MIDI.H - - author: James R. Dose - date: May 25, 1994 - - Public header for MIDI.C. Midi song file playback routines. - - (c) Copyright 1994 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#ifndef __MIDI_H -#define __MIDI_H - -#include "compat.h" -#include "midifuncs.h" - -enum MIDI_Errors -{ - MIDI_Warning = -2, - MIDI_Error = -1, - MIDI_Ok = 0, - MIDI_NullMidiModule, - MIDI_InvalidMidiFile, - MIDI_UnknownMidiFormat, - MIDI_NoTracks, - MIDI_InvalidTrack, - MIDI_NoMemory, - MIDI_DriverError -}; - - -#define MIDI_PASS_THROUGH 1 -#define MIDI_DONT_PLAY 0 - -#define MIDI_MaxVolume 255 - -int MIDI_AllNotesOff(void); -int MIDI_Reset(void); -int MIDI_SetVolume(int volume); -int MIDI_GetVolume(void); -void MIDI_SetMidiFuncs(midifuncs *funcs); -void MIDI_SetLoopFlag(int loopflag); -void MIDI_ContinueSong(void); -void MIDI_PauseSong(void); -void MIDI_StopSong(void); -int MIDI_PlaySong(char *song, int loopflag); -void MIDI_SetTempo(int tempo); -void MIDI_Restart(void); - -#endif diff --git a/source/audiolib/src/mix.cpp b/source/audiolib/src/mix.cpp deleted file mode 100644 index 331d5cd58..000000000 --- a/source/audiolib/src/mix.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -#include "_multivc.h" - -template uint32_t MV_MixMono(struct VoiceNode * const voice, uint32_t length); -template uint32_t MV_MixStereo(struct VoiceNode * const voice, uint32_t length); -template uint32_t MV_MixMono(struct VoiceNode * const voice, uint32_t length); -template uint32_t MV_MixStereo(struct VoiceNode * const voice, uint32_t length); -template void MV_Reverb(char const *src, char * const dest, const float volume, int count); - -/* - length = count of samples to mix - position = offset of starting sample in source - rate = resampling increment - volume = direct volume adjustment, 1.0 = no change - */ - -// mono source, mono output -template -uint32_t MV_MixMono(struct VoiceNode * const voice, uint32_t length) -{ - auto const source = (S const *)voice->sound; - auto dest = (D *)MV_MixDestination; - - uint32_t position = voice->position; - uint32_t const rate = voice->RateScale; - float const volume = voice->volume*MV_GlobalVolume; - - do - { - auto const isample0 = CONVERT_LE_SAMPLE_TO_SIGNED(source[position >> 16]); - - position += rate; - - *dest = MIX_SAMPLES(SCALE_SAMPLE(isample0, volume*voice->LeftVolume), *dest); - dest++; - - voice->LeftVolume = SMOOTH_VOLUME(voice->LeftVolume, voice->LeftVolumeDest); - } - while (--length); - - MV_MixDestination = (char *)dest; - - return position; -} - -// mono source, stereo output -template -uint32_t MV_MixStereo(struct VoiceNode * const voice, uint32_t length) -{ - auto const source = (S const *)voice->sound; - auto dest = (D *)MV_MixDestination; - - uint32_t position = voice->position; - uint32_t const rate = voice->RateScale; - float const volume = voice->volume*MV_GlobalVolume; - - do - { - auto const isample0 = CONVERT_LE_SAMPLE_TO_SIGNED(source[position >> 16]); - - position += rate; - - *dest = MIX_SAMPLES(SCALE_SAMPLE(isample0, volume*voice->LeftVolume), *dest); - *(dest + (MV_RightChannelOffset / sizeof(*dest))) - = MIX_SAMPLES(SCALE_SAMPLE(isample0, volume*voice->RightVolume), *(dest + (MV_RightChannelOffset / sizeof(*dest)))); - dest += 2; - - voice->LeftVolume = SMOOTH_VOLUME(voice->LeftVolume, voice->LeftVolumeDest); - voice->RightVolume = SMOOTH_VOLUME(voice->RightVolume, voice->RightVolumeDest); - } - while (--length); - - MV_MixDestination = (char *)dest; - - return position; -} - -template -void MV_Reverb(char const *src, char * const dest, const float volume, int count) -{ - auto input = (T const *)src; - auto output = (T *)dest; - - do - { - auto const isample0 = CONVERT_SAMPLE_TO_SIGNED(*input++); - *output++ = CONVERT_SAMPLE_FROM_SIGNED(SCALE_SAMPLE(isample0, volume)); - } - while (--count > 0); -} diff --git a/source/audiolib/src/mixst.cpp b/source/audiolib/src/mixst.cpp deleted file mode 100644 index 198989667..000000000 --- a/source/audiolib/src/mixst.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -#include "_multivc.h" - -template uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length); -template uint32_t MV_MixStereoStereo(struct VoiceNode * const voice, uint32_t length); -template uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length); -template uint32_t MV_MixStereoStereo(struct VoiceNode * const voice, uint32_t length); - -/* - length = count of samples to mix - position = offset of starting sample in source - rate = resampling increment - volume = direct volume adjustment, 1.0 = no change - */ - -// stereo source, mono output -template -uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length) -{ - auto const source = (S const *)voice->sound; - auto dest = (D *)MV_MixDestination; - - uint32_t position = voice->position; - uint32_t const rate = voice->RateScale; - float const volume = voice->volume*MV_GlobalVolume; - - do - { - auto const isample0 = CONVERT_LE_SAMPLE_TO_SIGNED(source[(position >> 16) << 1]); - auto const isample1 = CONVERT_LE_SAMPLE_TO_SIGNED(source[((position >> 16) << 1) + 1]); - - position += rate; - - *dest = MIX_SAMPLES((SCALE_SAMPLE((isample0 + isample1) >> 1, volume*voice->LeftVolume)), *dest); - dest++; - - voice->LeftVolume = SMOOTH_VOLUME(voice->LeftVolume, voice->LeftVolumeDest); - } - while (--length); - - MV_MixDestination = (char *)dest; - - return position; -} - -// stereo source, stereo output -template -uint32_t MV_MixStereoStereo(struct VoiceNode * const voice, uint32_t length) -{ - auto const source = (S const *)voice->sound; - auto dest = (D *)MV_MixDestination; - - uint32_t position = voice->position; - uint32_t const rate = voice->RateScale; - float const volume = voice->volume*MV_GlobalVolume; - - do - { - auto const isample0 = CONVERT_LE_SAMPLE_TO_SIGNED(source[(position >> 16) << 1]); - auto const isample1 = CONVERT_LE_SAMPLE_TO_SIGNED(source[((position >> 16) << 1) + 1]); - - position += rate; - - *dest = MIX_SAMPLES(SCALE_SAMPLE(isample0, volume*voice->LeftVolume), *dest); - *(dest + (MV_RightChannelOffset / sizeof(*dest))) - = MIX_SAMPLES(SCALE_SAMPLE(isample1, volume*voice->RightVolume), *(dest + (MV_RightChannelOffset / sizeof(*dest)))); - dest += 2; - - voice->LeftVolume = SMOOTH_VOLUME(voice->LeftVolume, voice->LeftVolumeDest); - voice->RightVolume = SMOOTH_VOLUME(voice->RightVolume, voice->RightVolumeDest); - } - while (--length); - - MV_MixDestination = (char *)dest; - - return position; -} diff --git a/source/audiolib/src/multivoc.cpp b/source/audiolib/src/multivoc.cpp deleted file mode 100644 index 96f2dc0fe..000000000 --- a/source/audiolib/src/multivoc.cpp +++ /dev/null @@ -1,1001 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. -Copyright (C) 2015 EDuke32 developers -Copyright (C) 2015 Voidpoint, LLC - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -/********************************************************************** - module: MULTIVOC.C - - author: James R. Dose - date: December 20, 1993 - - Routines to provide multichannel digitized sound playback for - Sound Blaster compatible sound cards. - - (c) Copyright 1993 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#include "multivoc.h" - -#include "_multivc.h" -#include "baselayer.h" -#include "compat.h" -#include "drivers.h" -#include "fx_man.h" -#include "linklist.h" -#include "osd.h" -#include "pitch.h" -#include "pragmas.h" - -static void MV_StopVoice(VoiceNode *voice); -static void MV_ServiceVoc(void); - -static VoiceNode *MV_GetVoice(int handle); - -static int MV_ReverbLevel; -static int MV_ReverbDelay; -static float MV_ReverbVolume; - -Pan MV_PanTable[MV_NUMPANPOSITIONS][MV_MAXVOLUME + 1]; - -int MV_Installed; -static int MV_TotalVolume = MV_MAXTOTALVOLUME; -static int MV_MaxVoices = 1; - -int MV_BufferSize = MV_MIXBUFFERSIZE; -static int MV_BufferLength; - -static int MV_NumberOfBuffers = MV_NUMBEROFBUFFERS; - -static int MV_Channels = 1; - -static int MV_ReverseStereo; - -int MV_MixRate; - -static int MV_BufferEmpty[MV_NUMBEROFBUFFERS]; -char *MV_MixBuffer[(MV_NUMBEROFBUFFERS << 1) + 1]; - -static VoiceNode *MV_Voices; -static VoiceNode VoiceList; -static VoiceNode VoicePool; - -static int MV_MixPage; - -void (*MV_Printf)(const char *fmt, ...) = OSD_Printf; -static void (*MV_CallBackFunc)(intptr_t); - -char *MV_MixDestination; -int MV_SampleSize = 1; -int MV_RightChannelOffset; - -int MV_ErrorCode = MV_NotInstalled; - -float MV_GlobalVolume = 1.f; -float MV_VolumeSmooth = 1.f; - -int MV_Locked; - -char *MV_MusicBuffer; -static void (*MV_MusicCallback)(void); -static int MV_MixMusic = FALSE; - -static bool MV_Mix(VoiceNode * const voice, int const buffer) -{ - if (voice->length == 0 && voice->GetSound(voice) != KeepPlaying) - return false; - - float const gv = MV_GlobalVolume; - - if (voice->priority == FX_MUSIC_PRIORITY) - MV_GlobalVolume = 1.f; - - int length = MV_MIXBUFFERSIZE; - uint32_t bufsiz = voice->FixedPointBufferSize; - uint32_t const rate = voice->RateScale; - - MV_MixDestination = MV_MixBuffer[buffer]; - - // Add this voice to the mix - do - { - int mixlen = length; - uint32_t const position = voice->position; - uint32_t const voclen = voice->length; - - // Check if the last sample in this buffer would be - // beyond the length of the sample block - if ((position + bufsiz) >= voclen) - { - if (position >= voclen) - { - voice->GetSound(voice); - break; - } - - mixlen = (voclen - position + rate - voice->channels) / rate; - } - - voice->position = voice->mix(voice, mixlen); - length -= mixlen; - - if (voice->position >= voclen) - { - // Get the next block of sound - if (voice->GetSound(voice) == NoMoreData) - { - MV_GlobalVolume = gv; - return false; - } - - // Get the position of the last sample in the buffer - if (length > (voice->channels - 1)) - bufsiz = voice->RateScale * (length - voice->channels); - } - } while (length > 0); - - MV_GlobalVolume = gv; - return true; -} - -void MV_PlayVoice(VoiceNode *voice) -{ - MV_Lock(); - LL::SortedInsert(&VoiceList, voice, &VoiceNode::priority); - voice->LeftVolume = voice->LeftVolumeDest; - voice->RightVolume = voice->RightVolumeDest; - MV_Unlock(); -} - -static void MV_CleanupVoice(VoiceNode *voice) -{ - if (MV_CallBackFunc) - MV_CallBackFunc(voice->callbackval); - - switch (voice->wavetype) - { - case FMT_VORBIS: MV_ReleaseVorbisVoice(voice); break; - //case FMT_ZMUSIC: MV_ReleaseZMusicVoice(voice); break; - default: break; - } - - voice->handle = 0; -} - -static void MV_StopVoice(VoiceNode *voice) -{ - MV_CleanupVoice(voice); - MV_Lock(); - // move the voice from the play list to the free list - LL::Move(voice, &VoicePool); - MV_Unlock(); -} - -/*--------------------------------------------------------------------- - JBF: no synchronisation happens inside MV_ServiceVoc nor the - supporting functions it calls. This would cause a deadlock - between the mixer thread in the driver vs the nested - locking in the user-space functions of MultiVoc. The call - to MV_ServiceVoc is synchronised in the driver. ----------------------------------------------------------------------*/ -static void MV_ServiceVoc(void) -{ - // Toggle which buffer we'll mix next - ++MV_MixPage &= MV_NumberOfBuffers-1; - - if (MV_ReverbLevel == 0) - { - if (!MV_BufferEmpty[MV_MixPage]) - { - Bmemset(MV_MixBuffer[MV_MixPage], 0, MV_BufferSize); - MV_BufferEmpty[ MV_MixPage ] = TRUE; - } - } - else - { - char const *const end = MV_MixBuffer[0] + MV_BufferLength; - char * dest = MV_MixBuffer[MV_MixPage]; - char const * source = MV_MixBuffer[MV_MixPage] - MV_ReverbDelay; - - if (source < MV_MixBuffer[ 0 ]) - source += MV_BufferLength; - - int length = MV_BufferSize; - - do - { - int const count = (source + length > end) ? (end - source) : length; - - MV_Reverb(source, dest, MV_ReverbVolume, count >> 1); - - // if we go through the loop again, it means that we've wrapped around the buffer - source = MV_MixBuffer[ 0 ]; - dest += count; - length -= count; - } while (length > 0); - } - - if (VoiceList.next && VoiceList.next != &VoiceList) - { - VoiceNode *voice = VoiceList.next; - VoiceNode *next; - - do - { - next = voice->next; - - if (voice->Paused) - continue; - - MV_BufferEmpty[ MV_MixPage ] = FALSE; - - // Is this voice done? - if (!MV_Mix(voice, MV_MixPage)) - { - MV_CleanupVoice(voice); - LL::Move(voice, &VoicePool); - } - } - while ((voice = next) != &VoiceList); - } - - Bmemcpy(MV_MixBuffer[MV_MixPage+MV_NumberOfBuffers], MV_MixBuffer[MV_MixPage], MV_BufferSize); - - if (MV_MixMusic) - { - MV_MusicCallback(); - int16_t *source = (int16_t*)MV_MusicBuffer; - int16_t *dest = (int16_t*)MV_MixBuffer[MV_MixPage+MV_NumberOfBuffers]; - for (int32_t i = 0; i < MV_BufferSize>>2; i++) - { - int32_t sl = *source++; - int32_t sr = *source++; - *dest = clamp(*dest+sl,INT16_MIN, INT16_MAX); - dest++; - *dest = clamp(*dest+sr,INT16_MIN, INT16_MAX); - dest++; - } - } -} - -static VoiceNode *MV_GetVoice(int handle) -{ - if (handle < MV_MINVOICEHANDLE || handle > MV_MaxVoices) - { - //MV_Printf("MV_GetVoice(): bad handle (%d)!\n", handle); - return nullptr; - } - - MV_Lock(); - - for (VoiceNode *voice = VoiceList.next; voice != &VoiceList; voice = voice->next) - { - if (handle == voice->handle) - { - MV_Unlock(); - return voice; - } - } - - MV_Unlock(); - MV_SetErrorCode(MV_VoiceNotFound); - return nullptr; -} - -VoiceNode *MV_BeginService(int handle) -{ - if (!MV_Installed) - return nullptr; - - VoiceNode *voice = MV_GetVoice(handle); - - if (voice == nullptr) - { - MV_SetErrorCode(MV_VoiceNotFound); - return nullptr; - } - - MV_Lock(); - - return voice; -} - -static inline void MV_EndService(void) { MV_Unlock(); } - -int MV_VoicePlaying(int handle) -{ - return (MV_Installed && MV_GetVoice(handle)) ? TRUE : FALSE; -} - -int MV_KillAllVoices(void) -{ - if (!MV_Installed) - return MV_Error; - - MV_Lock(); - - if (&VoiceList == VoiceList.next) - { - MV_Unlock(); - return MV_Ok; - } - - VoiceNode * voice = VoiceList.prev; - - // Remove all the voices from the list - while (voice != &VoiceList) - { - if (voice->priority == MV_MUSIC_PRIORITY) - { - voice = voice->prev; - continue; - } - - MV_Kill(voice->handle); - voice = VoiceList.prev; - } - - MV_Unlock(); - - return MV_Ok; -} - -int MV_Kill(int handle) -{ - VoiceNode *voice = MV_BeginService(handle); - - if (voice == nullptr) - return MV_Error; - - MV_StopVoice(voice); - MV_EndService(); - - return MV_Ok; -} - -int MV_VoicesPlaying(void) -{ - if (!MV_Installed) - return 0; - - MV_Lock(); - - int NumVoices = 0; - - for (VoiceNode *voice = VoiceList.next; voice != &VoiceList; voice = voice->next) - NumVoices++; - - MV_Unlock(); - - return NumVoices; -} - -VoiceNode *MV_AllocVoice(int priority) -{ - VoiceNode *voice; - - MV_Lock(); - - // Check if we have any free voices - if (LL::Empty(&VoicePool)) - { - // check if we have a higher priority than a voice that is playing. - for (auto node = voice = VoiceList.next; node != &VoiceList; node = node->next) - { - if (node->priority < voice->priority) - voice = node; - } - - if (priority >= voice->priority && voice != &VoiceList && voice->handle >= MV_MINVOICEHANDLE) - MV_Kill(voice->handle); - - if (LL::Empty(&VoicePool)) - { - // No free voices - MV_Unlock(); - return nullptr; - } - } - - voice = VoicePool.next; - LL::Remove(voice); - MV_Unlock(); - - int vhan = MV_MINVOICEHANDLE; - - // Find a free voice handle - do - { - if (++vhan < MV_MINVOICEHANDLE || vhan > MV_MaxVoices) - vhan = MV_MINVOICEHANDLE; - } while (MV_VoicePlaying(vhan)); - - voice->handle = vhan; - - return voice; -} - -int MV_VoiceAvailable(int priority) -{ - // Check if we have any free voices - if (!LL::Empty(&VoicePool)) - return TRUE; - - MV_Lock(); - - VoiceNode *voice; - - // check if we have a higher priority than a voice that is playing. - for (auto node = voice = VoiceList.next; node != &VoiceList; node = node->next) - { - if (node->priority < voice->priority) - voice = node; - } - - if ((voice == &VoiceList) || (priority < voice->priority)) - { - MV_Unlock(); - return FALSE; - } - - MV_Unlock(); - return TRUE; -} - -void MV_SetVoicePitch(VoiceNode *voice, uint32_t rate, int pitchoffset) -{ - voice->SamplingRate = rate; - voice->PitchScale = PITCH_GetScale(pitchoffset); - voice->RateScale = divideu32(rate * voice->PitchScale, MV_MixRate); - - // Multiply by MV_MIXBUFFERSIZE - 1 - voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - - voice->RateScale; -} - -int MV_SetPitch(int handle, int pitchoffset) -{ - VoiceNode *voice = MV_BeginService(handle); - - if (voice == nullptr) - return MV_Error; - - MV_SetVoicePitch(voice, voice->SamplingRate, pitchoffset); - MV_EndService(); - - return MV_Ok; -} - -int MV_SetFrequency(int handle, int frequency) -{ - VoiceNode *voice = MV_BeginService(handle); - - if (voice == nullptr) - return MV_Error; - - MV_SetVoicePitch(voice, frequency, 0); - MV_EndService(); - - return MV_Ok; -} - -int32_t MV_GetFrequency(int32_t handle, int32_t *frequency) -{ - VoiceNode* voice = MV_BeginService(handle); - - if (voice == NULL || !frequency) - return MV_Error; - - if (voice->SamplingRate == 0) - voice->GetSound(voice); - - *frequency = voice->SamplingRate; - MV_EndService(); - - return MV_Ok; -} - -/*--------------------------------------------------------------------- - Function: MV_SetVoiceMixMode - - Selects which method should be used to mix the voice. - - 16Bit 16Bit | 8Bit 16Bit 8Bit 16Bit | - Mono Ster | Mono Mono Ster Ster | Mixer - Out Out | In In In In | -----------------------+---------------------------+------------- - X | X | MixMono - X | X | MixMono - X | X | MixStereo - X | X | MixStereo -----------------------+---------------------------+------------- - X | X | MixStereoStereo - X | X | MixStereoStereo - X | X | MixMonoStereo - X | X | MixMonoStereo ----------------------------------------------------------------------*/ - -void MV_SetVoiceMixMode(VoiceNode *voice) -{ - int type = T_DEFAULT; - - if (MV_Channels == 1) - type |= T_MONO; - - if (voice->bits == 16) - type |= T_16BITSOURCE; - - if (voice->channels == 2) - type |= T_STEREOSOURCE; - - // stereo look-up table - static constexpr decltype(voice->mix) mixslut[] - = { MV_MixStereo, MV_MixMono, MV_MixStereo, MV_MixMono, - MV_MixStereoStereo, MV_MixMonoStereo, MV_MixStereoStereo, MV_MixMonoStereo }; - - voice->mix = mixslut[type]; -} - -void MV_SetVoiceVolume(VoiceNode *voice, int vol, int left, int right, float volume) -{ - if (MV_Channels == 1) - left = right = vol; - else if (MV_ReverseStereo) - swap(&left, &right); - - voice->LeftVolumeDest = float(left)*(1.f/MV_MAXTOTALVOLUME); - voice->RightVolumeDest = float(right)*(1.f/MV_MAXTOTALVOLUME); - voice->volume = volume; - - MV_SetVoiceMixMode(voice); -} - -int MV_PauseVoice(int handle, int pause) -{ - VoiceNode *voice = MV_BeginService(handle); - - if (voice == nullptr) - return MV_Error; - - voice->Paused = pause; - MV_EndService(); - - return MV_Ok; -} - -int MV_EndLooping(int handle) -{ - VoiceNode *voice = MV_BeginService(handle); - - if (voice == nullptr) - return MV_Error; - - voice->LoopCount = 0; - voice->LoopStart = nullptr; - voice->LoopEnd = nullptr; - - MV_EndService(); - - return MV_Ok; -} - -int MV_SetPan(int handle, int vol, int left, int right) -{ - VoiceNode *voice = MV_BeginService(handle); - - if (voice == nullptr) - return MV_Error; - - MV_SetVoiceVolume(voice, vol, left, right, voice->volume); - MV_EndService(); - return MV_Ok; -} - -int MV_Pan3D(int handle, int angle, int distance) -{ - if (distance < 0) - { - distance = -distance; - angle += MV_NUMPANPOSITIONS / 2; - } - - int const volume = MIX_VOLUME(distance); - - angle &= MV_MAXPANPOSITION; - - return MV_SetPan(handle, max(0, 255 - distance), - MV_PanTable[ angle ][ volume ].left, - MV_PanTable[ angle ][ volume ].right); -} - -void MV_SetReverb(int reverb) -{ - MV_ReverbLevel = MIX_VOLUME(reverb); - MV_ReverbVolume = float(MV_ReverbLevel)*(1.f/MV_MAXVOLUME); -} - -int MV_GetMaxReverbDelay(void) { return MV_MIXBUFFERSIZE * MV_NumberOfBuffers; } -int MV_GetReverbDelay(void) { return tabledivide32(MV_ReverbDelay, MV_SampleSize); } - -void MV_SetReverbDelay(int delay) -{ - MV_ReverbDelay = max(MV_MIXBUFFERSIZE, min(delay, MV_GetMaxReverbDelay())) * MV_SampleSize; -} - -static int MV_SetMixMode(int numchannels) -{ - if (!MV_Installed) - return MV_Error; - - MV_Channels = 1 + (numchannels == 2); - MV_SampleSize = sizeof(int8_t) * MV_Channels * 2; - - MV_BufferSize = MV_MIXBUFFERSIZE * MV_SampleSize; - MV_NumberOfBuffers = tabledivide32(MV_TOTALBUFFERSIZE, MV_BufferSize); - Bassert(isPow2(MV_NumberOfBuffers)); - MV_BufferLength = MV_TOTALBUFFERSIZE; - - MV_RightChannelOffset = MV_SampleSize >> 1; - - return MV_Ok; -} - -static int MV_StartPlayback(void) -{ - // Initialize the buffers - Bmemset(MV_MixBuffer[0], 0, MV_TOTALBUFFERSIZE << 1); - - for (int buffer = 0; buffer < MV_NumberOfBuffers; buffer++) - MV_BufferEmpty[buffer] = TRUE; - - MV_MixPage = 1; - - if (SoundDriver_PCM_BeginPlayback(MV_MixBuffer[MV_NumberOfBuffers], MV_BufferSize, MV_NumberOfBuffers, MV_ServiceVoc) != MV_Ok) - return MV_SetErrorCode(MV_DriverError); - - return MV_Ok; -} - -static void MV_StopPlayback(void) -{ - SoundDriver_PCM_StopPlayback(); - - // Make sure all callbacks are done. - MV_Lock(); - - for (VoiceNode *voice = VoiceList.next, *next; voice != &VoiceList; voice = next) - { - next = voice->next; - MV_StopVoice(voice); - } - - MV_Unlock(); -} - -static void MV_CalcPanTable(void) -{ - const int HalfAngle = MV_NUMPANPOSITIONS / 2; - const int QuarterAngle = HalfAngle / 2; - - for (int distance = 0; distance <= MV_MAXVOLUME; distance++) - { - const int level = (255 * (MV_MAXVOLUME - distance)) / MV_MAXVOLUME; - - for (int angle = 0; angle <= QuarterAngle; angle++) - { - const int ramp = level - (level * angle) / QuarterAngle; - - MV_PanTable[angle][distance].left = ramp; - MV_PanTable[angle][distance].right = level; - - MV_PanTable[HalfAngle - angle][distance].left = ramp; - MV_PanTable[HalfAngle - angle][distance].right = level; - - MV_PanTable[HalfAngle + angle][distance].left = level; - MV_PanTable[HalfAngle + angle][distance].right = ramp; - - MV_PanTable[MV_MAXPANPOSITION - angle][distance].left = level; - MV_PanTable[MV_MAXPANPOSITION - angle][distance].right = ramp; - } - } -} - -void MV_SetVolume(int volume) -{ - MV_TotalVolume = min(max(0, volume), MV_MAXTOTALVOLUME); - MV_GlobalVolume = (float)volume / 255.f; - // MV_CalcVolume(MV_TotalVolume); -} - -int MV_GetVolume(void) { return MV_TotalVolume; } - -void MV_SetCallBack(void (*function)(intptr_t)) { MV_CallBackFunc = function; } - -void MV_SetReverseStereo(int setting) { MV_ReverseStereo = setting; } - -int MV_GetReverseStereo(void) { return MV_ReverseStereo; } - -int MV_Init(int soundcard, int MixRate, int Voices, int numchannels, void *initdata) -{ - if (MV_Installed) - MV_Shutdown(); - - MV_SetErrorCode(MV_Ok); - - // MV_TotalMemory + 2: FIXME, see valgrind_errors.log - int const totalmem = Voices * sizeof(VoiceNode) + (MV_TOTALBUFFERSIZE<<1) + (MV_MIXBUFFERSIZE<<2) + 2; - - char *ptr = (char *) Xaligned_alloc(16, totalmem); - - if (!ptr) - return MV_SetErrorCode(MV_NoMem); - - Bmemset(ptr, 0, totalmem); - - MV_Voices = (VoiceNode *)ptr; - ptr += Voices * sizeof(VoiceNode); - - MV_MaxVoices = Voices; - - LL::Reset((VoiceNode*) &VoiceList); - LL::Reset((VoiceNode*) &VoicePool); - - for (int index = 0; index < Voices; index++) - LL::Insert(&VoicePool, &MV_Voices[index]); - - MV_SetReverseStereo(FALSE); - - ASS_PCMSoundDriver = soundcard; - - // Initialize the sound card - - if (SoundDriver_PCM_Init(&MixRate, &numchannels, initdata) != MV_Ok) - MV_SetErrorCode(MV_DriverError); - - if (MV_ErrorCode != MV_Ok) - { - ALIGNED_FREE_AND_NULL(MV_Voices); - - return MV_Error; - } - - MV_Installed = TRUE; - MV_CallBackFunc = nullptr; - MV_ReverbLevel = 0; - MV_ReverbVolume = 0.f; - - // Set the sampling rate - MV_MixRate = MixRate; - - // Set Mixer to play stereo digitized sound - MV_SetMixMode(numchannels); - MV_ReverbDelay = MV_BufferSize * 3; - - // Make sure we don't cross a physical page - MV_MixBuffer[ MV_NumberOfBuffers<<1 ] = ptr; - for (int buffer = 0; buffer < MV_NumberOfBuffers<<1; buffer++) - { - MV_MixBuffer[ buffer ] = ptr; - ptr += MV_BufferSize; - } - - MV_MusicBuffer = ptr; - - // Calculate pan table - MV_CalcPanTable(); - - MV_VolumeSmooth = 1.f-powf(0.1f, 30.f/MixRate); - - // Start the playback engine - if (MV_StartPlayback() != MV_Ok) - { - // Preserve error code while we shutdown. - int status = MV_ErrorCode; - MV_Shutdown(); - return MV_SetErrorCode(status); - } - - return MV_Ok; -} - -int MV_Shutdown(void) -{ - if (!MV_Installed) - return MV_Ok; - - MV_KillAllVoices(); - - MV_Installed = FALSE; - - // Stop the sound playback engine - MV_StopPlayback(); - - // Shutdown the sound card - SoundDriver_PCM_Shutdown(); - - // Free any voices we allocated - ALIGNED_FREE_AND_NULL(MV_Voices); - - LL::Reset((VoiceNode*) &VoiceList); - LL::Reset((VoiceNode*) &VoicePool); - - MV_MaxVoices = 1; - - // Release the descriptor from our mix buffer - for (int buffer = 0; buffer < MV_NUMBEROFBUFFERS<<1; buffer++) - MV_MixBuffer[ buffer ] = nullptr; - - MV_SetErrorCode(MV_NotInstalled); - - return MV_Ok; -} - -void MV_HookMusicRoutine(void(*callback)(void)) -{ - MV_Lock(); - MV_MusicCallback = callback; - MV_MixMusic = TRUE; - MV_Unlock(); -} - -void MV_UnhookMusicRoutine(void) -{ - if (MV_MusicCallback) - { - MV_Lock(); - MV_MusicCallback = nullptr; - MV_MixMusic = FALSE; - MV_Unlock(); - } -} - -MV_MusicRoutineBuffer MV_GetMusicRoutineBuffer() -{ - return MV_MusicRoutineBuffer{ MV_MusicBuffer, MV_BufferSize }; -} - -const char *loopStartTags[loopStartTagCount] = { "LOOP_START", "LOOPSTART", "LOOP" }; -const char *loopEndTags[loopEndTagCount] = { "LOOP_END", "LOOPEND" }; -const char *loopLengthTags[loopLengthTagCount] = { "LOOP_LENGTH", "LOOPLENGTH" }; - -const char *MV_ErrorString(int ErrorNumber) -{ - switch (ErrorNumber) - { - case MV_Error: - return MV_ErrorString(MV_ErrorCode); - case MV_Ok: - return "Multivoc ok."; - case MV_NotInstalled: - return "Multivoc not installed."; - case MV_DriverError: - return SoundDriver_PCM_ErrorString(SoundDriver_PCM_GetError()); - case MV_NoVoices: - return "No free voices available to Multivoc."; - case MV_NoMem: - return "Out of memory in Multivoc."; - case MV_VoiceNotFound: - return "No voice with matching handle found."; - case MV_InvalidFile: - return "Invalid file passed in to Multivoc."; - default: - return "Unknown Multivoc error code."; - } -} - -/*--------------------------------------------------------------------- - Function: MV_GetNextDemandFeedBlock - - Controls playback of demand fed data. ----------------------------------------------------------------------*/ - -playbackstatus MV_GetNextDemandFeedBlock -( - VoiceNode* voice -) - -{ - if (voice->BlockLength > 0) - { - voice->position -= voice->length; - voice->sound += voice->length >> 16; - voice->length = min(voice->BlockLength, 0x8000u); - voice->BlockLength -= voice->length; - voice->length <<= 16; - - return(KeepPlaying); - } - - if (voice->DemandFeed == NULL) - { - return(NoMoreData); - } - - voice->position = 0; - (voice->DemandFeed)(&voice->sound, &voice->BlockLength); - voice->length = min(voice->BlockLength, 0x8000u); - voice->BlockLength -= voice->length; - voice->length <<= 16; - - if ((voice->length > 0) && (voice->sound != NULL)) - { - return(KeepPlaying); - } - return(NoMoreData); -} - -/*--------------------------------------------------------------------- - Function: MV_StartDemandFeedPlayback - - Plays a digitized sound from a user controlled buffering system. ----------------------------------------------------------------------*/ - -int MV_StartDemandFeedPlayback -( - void (*function)(const char** ptr, uint32_t* length), - int rate, - int pitchoffset, - int vol, - int left, - int right, - int priority, - fix16_t volume, - uint32_t callbackval -) - -{ - VoiceNode* voice; - - if (!MV_Installed) - { - MV_SetErrorCode(MV_NotInstalled); - return(MV_Error); - } - - // Request a voice from the voice pool - voice = MV_AllocVoice(priority); - if (voice == NULL) - { - MV_SetErrorCode(MV_NoVoices); - return(MV_Error); - } - -// voice->wavetype = FMT_DEMANDFED; - voice->bits = 8; - voice->channels = 1; - voice->GetSound = MV_GetNextDemandFeedBlock; - voice->NextBlock = NULL; - voice->DemandFeed = function; - voice->LoopStart = NULL; - voice->LoopCount = 0; - voice->BlockLength = 0; - voice->position = 0; - voice->sound = NULL; - voice->length = 0; - voice->next = NULL; - voice->prev = NULL; - voice->priority = priority; - voice->callbackval = callbackval; - - MV_SetVoicePitch(voice, rate, pitchoffset); - MV_SetVoiceVolume(voice, vol, left, right, volume); - MV_PlayVoice(voice); - - return(voice->handle); -} diff --git a/source/audiolib/src/music.cpp b/source/audiolib/src/music.cpp deleted file mode 100644 index c0c4f03f2..000000000 --- a/source/audiolib/src/music.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2010-2019 EDuke32 developers and contributors -Copyright (C) 2019 Nuke.YKT - -This file is part of NBlood. - -NBlood is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- - -#include "music.h" - -#include "compat.h" -#include "drivers.h" -#include "midi.h" -#include "multivoc.h" -#include "sndcards.h" - -int MUSIC_ErrorCode = MUSIC_Ok; - -static midifuncs MUSIC_MidiFunctions; - -#define MUSIC_SetErrorCode(status) MUSIC_ErrorCode = (status); - -const char *MUSIC_ErrorString(int ErrorNumber) -{ - const char *ErrorString; - - switch (ErrorNumber) - { - case MUSIC_Warning: - case MUSIC_Error: ErrorString = MUSIC_ErrorString(MUSIC_ErrorCode); break; - case MUSIC_Ok: ErrorString = "Music ok."; break; - case MUSIC_MidiError: ErrorString = "Error playing MIDI file."; break; - default: ErrorString = "Unknown Music error code."; break; - } - - return ErrorString; -} - - -int MUSIC_Init(int SoundCard) -{ - int detected = 0; - - if (SoundCard == ASS_AutoDetect) - { -redetect: - detected++; - SoundCard = ASS_OPL3; - } - - if (SoundCard < 0 || SoundCard >= ASS_NumSoundCards) - { -failed: - MV_Printf("failed!\n"); - MUSIC_ErrorCode = MUSIC_MidiError; - return MUSIC_Error; - } - - if (!SoundDriver_IsMIDISupported(SoundCard)) - { - MV_Printf("Couldn't init %s\n", SoundDriver_GetName(SoundCard)); - - if (detected < 2) - goto redetect; - - goto failed; - } - - ASS_MIDISoundDriver = SoundCard; - - int status = SoundDriver_MIDI_Init(&MUSIC_MidiFunctions); - - if (status != MUSIC_Ok) - { - if (detected < 2) - goto redetect; - - goto failed; - } - - MV_Printf("%s\n", SoundDriver_GetName(SoundCard)); - - MIDI_SetMidiFuncs(&MUSIC_MidiFunctions); - - return MUSIC_Ok; -} - - -int MUSIC_Shutdown(void) -{ - MIDI_StopSong(); - - return MUSIC_Ok; -} - - -void MUSIC_SetVolume(int volume) { MIDI_SetVolume(min(max(0, volume), 255)); } - - -int MUSIC_GetVolume(void) { return MIDI_GetVolume(); } -void MUSIC_SetLoopFlag(int loopflag) { MIDI_SetLoopFlag(loopflag); } -void MUSIC_Continue(void) { MIDI_ContinueSong(); } -void MUSIC_Pause(void) { MIDI_PauseSong(); } - -int MUSIC_StopSong(void) -{ - MIDI_StopSong(); - MUSIC_SetErrorCode(MUSIC_Ok); - return MUSIC_Ok; -} - - -int MUSIC_PlaySong(char *song, int songsize, int loopflag, const char *fn /*= nullptr*/) -{ - UNREFERENCED_PARAMETER(songsize); - UNREFERENCED_PARAMETER(fn); - - MUSIC_SetErrorCode(MUSIC_Ok) - - if (MIDI_PlaySong(song, loopflag) != MIDI_Ok) - { - MUSIC_SetErrorCode(MUSIC_MidiError); - return MUSIC_Warning; - } - - return MUSIC_Ok; -} - - -void MUSIC_Update(void) -{ -} diff --git a/source/audiolib/src/opl3.cpp b/source/audiolib/src/opl3.cpp deleted file mode 100644 index 0efea236c..000000000 --- a/source/audiolib/src/opl3.cpp +++ /dev/null @@ -1,1398 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 2013-2019 Nuke.YKT - -This file is part of NBlood. - -NBlood is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License version 2 -as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- -// -// Nuked OPL3 emulator. -// Thanks: -// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): -// Feedback and Rhythm part calculation information. -// forums.submarine.org.uk(carbon14, opl3): -// Tremolo and phase generator calculation information. -// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): -// OPL2 ROMs. -// siliconpr0n.org(John McMaster, digshadow): -// YMF262 and VRC VII decaps and die shots. -// -// version: 1.8, with stereo extension -// - -#include -#include -#include -#define _USE_MATH_DEFINES -#include -#include "opl3.h" - -#define RSM_FRAC 10 - -// Channel types - -enum { - ch_2op = 0, - ch_4op = 1, - ch_4op2 = 2, - ch_drum = 3 -}; - -// Envelope key types - -enum { - egk_norm = 0x01, - egk_drum = 0x02 -}; - - -// -// logsin table -// - -static const Bit16u logsinrom[256] = { - 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, - 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365, - 0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd, - 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261, - 0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f, - 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd, - 0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195, - 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166, - 0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c, - 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118, - 0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8, - 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db, - 0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1, - 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9, - 0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094, - 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081, - 0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070, - 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060, - 0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052, - 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045, - 0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039, - 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f, - 0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026, - 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e, - 0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017, - 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011, - 0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c, - 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007, - 0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004, - 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002, - 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 -}; - -// -// exp table -// - -static const Bit16u exprom[256] = { - 0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4, - 0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9, - 0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f, - 0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756, - 0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e, - 0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706, - 0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0, - 0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba, - 0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695, - 0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671, - 0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e, - 0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b, - 0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609, - 0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8, - 0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8, - 0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8, - 0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589, - 0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b, - 0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d, - 0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530, - 0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514, - 0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8, - 0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc, - 0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2, - 0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8, - 0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e, - 0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475, - 0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d, - 0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445, - 0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d, - 0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416, - 0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400 -}; - -// -// freq mult table multiplied by 2 -// -// 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 -// - -static const Bit8u mt[16] = { - 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 -}; - -// -// ksl table -// - -static const Bit8u kslrom[16] = { - 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 -}; - -static const Bit8u kslshift[4] = { - 8, 1, 2, 0 -}; - -// -// envelope generator constants -// - -static const Bit8u eg_incstep[4][4] = { - { 0, 0, 0, 0 }, - { 1, 0, 0, 0 }, - { 1, 0, 1, 0 }, - { 1, 1, 1, 0 } -}; - -// -// address decoding -// - -static const Bit8s ad_slot[0x20] = { - 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, - 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static const Bit8u ch_slot[18] = { - 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 -}; - -static Bit32s panpot_lut[256]; -static Bit8u panpot_lut_build = 0; - -// -// Envelope generator -// - -typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope); -typedef void(*envelope_genfunc)(opl3_slot *slott); - -static Bit16s OPL3_EnvelopeCalcExp(Bit32u level) -{ - if (level > 0x1fff) - { - level = 0x1fff; - } - return (exprom[level & 0xff] << 1) >> (level >> 8); -} - -static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - Bit16u neg = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - neg = 0xffff; - } - if (phase & 0x100) - { - out = logsinrom[(phase & 0xff) ^ 0xff]; - } - else - { - out = logsinrom[phase & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; -} - -static Bit16s OPL3_EnvelopeCalcSin1(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - out = 0x1000; - } - else if (phase & 0x100) - { - out = logsinrom[(phase & 0xff) ^ 0xff]; - } - else - { - out = logsinrom[phase & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)); -} - -static Bit16s OPL3_EnvelopeCalcSin2(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - phase &= 0x3ff; - if (phase & 0x100) - { - out = logsinrom[(phase & 0xff) ^ 0xff]; - } - else - { - out = logsinrom[phase & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)); -} - -static Bit16s OPL3_EnvelopeCalcSin3(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - phase &= 0x3ff; - if (phase & 0x100) - { - out = 0x1000; - } - else - { - out = logsinrom[phase & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)); -} - -static Bit16s OPL3_EnvelopeCalcSin4(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - Bit16u neg = 0; - phase &= 0x3ff; - if ((phase & 0x300) == 0x100) - { - neg = 0xffff; - } - if (phase & 0x200) - { - out = 0x1000; - } - else if (phase & 0x80) - { - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; - } - else - { - out = logsinrom[(phase << 1) & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; -} - -static Bit16s OPL3_EnvelopeCalcSin5(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - out = 0x1000; - } - else if (phase & 0x80) - { - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; - } - else - { - out = logsinrom[(phase << 1) & 0xff]; - } - return OPL3_EnvelopeCalcExp(out + (envelope << 3)); -} - -static Bit16s OPL3_EnvelopeCalcSin6(Bit16u phase, Bit16u envelope) -{ - Bit16u neg = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - neg = 0xffff; - } - return OPL3_EnvelopeCalcExp(envelope << 3) ^ neg; -} - -static Bit16s OPL3_EnvelopeCalcSin7(Bit16u phase, Bit16u envelope) -{ - Bit16u out = 0; - Bit16u neg = 0; - phase &= 0x3ff; - if (phase & 0x200) - { - neg = 0xffff; - phase = (phase & 0x1ff) ^ 0x1ff; - } - out = phase << 3; - return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg; -} - -static const envelope_sinfunc envelope_sin[8] = { - OPL3_EnvelopeCalcSin0, - OPL3_EnvelopeCalcSin1, - OPL3_EnvelopeCalcSin2, - OPL3_EnvelopeCalcSin3, - OPL3_EnvelopeCalcSin4, - OPL3_EnvelopeCalcSin5, - OPL3_EnvelopeCalcSin6, - OPL3_EnvelopeCalcSin7 -}; - -enum envelope_gen_num -{ - envelope_gen_num_attack = 0, - envelope_gen_num_decay = 1, - envelope_gen_num_sustain = 2, - envelope_gen_num_release = 3 -}; - -static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) -{ - Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2) - - ((0x08 - slot->channel->block) << 5); - if (ksl < 0) - { - ksl = 0; - } - slot->eg_ksl = (Bit8u)ksl; -} - -static void OPL3_EnvelopeCalc(opl3_slot *slot) -{ - Bit8u nonzero; - Bit8u rate; - Bit8u rate_hi; - Bit8u rate_lo; - Bit8u reg_rate = 0; - Bit8u ks; - Bit8u eg_shift, shift; - Bit16u eg_rout; - Bit16s eg_inc; - Bit8u eg_off; - Bit8u reset = 0; - slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) - + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; - if (slot->key && slot->eg_gen == envelope_gen_num_release) - { - reset = 1; - reg_rate = slot->reg_ar; - } - else - { - switch (slot->eg_gen) - { - case envelope_gen_num_attack: - reg_rate = slot->reg_ar; - break; - case envelope_gen_num_decay: - reg_rate = slot->reg_dr; - break; - case envelope_gen_num_sustain: - if (!slot->reg_type) - { - reg_rate = slot->reg_rr; - } - break; - case envelope_gen_num_release: - reg_rate = slot->reg_rr; - break; - } - } - slot->pg_reset = reset; - ks = slot->channel->ksv >> ((slot->reg_ksr ^ 1) << 1); - nonzero = (reg_rate != 0); - rate = ks + (reg_rate << 2); - rate_hi = rate >> 2; - rate_lo = rate & 0x03; - if (rate_hi & 0x10) - { - rate_hi = 0x0f; - } - eg_shift = rate_hi + slot->chip->eg_add; - shift = 0; - if (nonzero) - { - if (rate_hi < 12) - { - if (slot->chip->eg_state) - { - switch (eg_shift) - { - case 12: - shift = 1; - break; - case 13: - shift = (rate_lo >> 1) & 0x01; - break; - case 14: - shift = rate_lo & 0x01; - break; - default: - break; - } - } - } - else - { - shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03]; - if (shift & 0x04) - { - shift = 0x03; - } - if (!shift) - { - shift = slot->chip->eg_state; - } - } - } - eg_rout = slot->eg_rout; - eg_inc = 0; - eg_off = 0; - // Instant attack - if (reset && rate_hi == 0x0f) - { - eg_rout = 0x00; - } - // Envelope off - if ((slot->eg_rout & 0x1f8) == 0x1f8) - { - eg_off = 1; - } - if (slot->eg_gen != envelope_gen_num_attack && !reset && eg_off) - { - eg_rout = 0x1ff; - } - switch (slot->eg_gen) - { - case envelope_gen_num_attack: - if (!slot->eg_rout) - { - slot->eg_gen = envelope_gen_num_decay; - } - else if (slot->key && shift > 0 && rate_hi != 0x0f) - { - eg_inc = ((~slot->eg_rout) << shift) >> 4; - } - break; - case envelope_gen_num_decay: - if ((slot->eg_rout >> 4) == slot->reg_sl) - { - slot->eg_gen = envelope_gen_num_sustain; - } - else if (!eg_off && !reset && shift > 0) - { - eg_inc = 1 << (shift - 1); - } - break; - case envelope_gen_num_sustain: - case envelope_gen_num_release: - if (!eg_off && !reset && shift > 0) - { - eg_inc = 1 << (shift - 1); - } - break; - } - slot->eg_rout = (eg_rout + eg_inc) & 0x1ff; - // Key off - if (reset) - { - slot->eg_gen = envelope_gen_num_attack; - } - if (!slot->key) - { - slot->eg_gen = envelope_gen_num_release; - } -} - -static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type) -{ - slot->key |= type; -} - -static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) -{ - slot->key &= ~type; -} - -// -// Phase Generator -// - -static void OPL3_PhaseGenerate(opl3_slot *slot) -{ - opl3_chip *chip; - Bit16u f_num; - Bit32u basefreq; - Bit8u rm_xor, n_bit; - Bit32u noise; - Bit16u phase; - - chip = slot->chip; - f_num = slot->channel->f_num; - if (slot->reg_vib) - { - Bit8s range; - Bit8u vibpos; - - range = (f_num >> 7) & 7; - vibpos = slot->chip->vibpos; - - if (!(vibpos & 3)) - { - range = 0; - } - else if (vibpos & 1) - { - range >>= 1; - } - range >>= slot->chip->vibshift; - - if (vibpos & 4) - { - range = -range; - } - f_num += range; - } - basefreq = (f_num << slot->channel->block) >> 1; - phase = (Bit16u)(slot->pg_phase >> 9); - if (slot->pg_reset) - { - slot->pg_phase = 0; - } - slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; - // Rhythm mode - noise = chip->noise; - slot->pg_phase_out = phase; - if (slot->slot_num == 13) // hh - { - chip->rm_hh_bit2 = (phase >> 2) & 1; - chip->rm_hh_bit3 = (phase >> 3) & 1; - chip->rm_hh_bit7 = (phase >> 7) & 1; - chip->rm_hh_bit8 = (phase >> 8) & 1; - } - if (slot->slot_num == 17 && (chip->rhy & 0x20)) // tc - { - chip->rm_tc_bit3 = (phase >> 3) & 1; - chip->rm_tc_bit5 = (phase >> 5) & 1; - } - if (chip->rhy & 0x20) - { - rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) - | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) - | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); - switch (slot->slot_num) - { - case 13: // hh - slot->pg_phase_out = rm_xor << 9; - if (rm_xor ^ (noise & 1)) - { - slot->pg_phase_out |= 0xd0; - } - else - { - slot->pg_phase_out |= 0x34; - } - break; - case 16: // sd - slot->pg_phase_out = (chip->rm_hh_bit8 << 9) - | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); - break; - case 17: // tc - slot->pg_phase_out = (rm_xor << 9) | 0x80; - break; - default: - break; - } - } - n_bit = ((noise >> 14) ^ noise) & 0x01; - chip->noise = (noise >> 1) | (n_bit << 22); -} - -// -// Slot -// - -static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data) -{ - if ((data >> 7) & 0x01) - { - slot->trem = &slot->chip->tremolo; - } - else - { - slot->trem = (Bit8u*)&slot->chip->zeromod; - } - slot->reg_vib = (data >> 6) & 0x01; - slot->reg_type = (data >> 5) & 0x01; - slot->reg_ksr = (data >> 4) & 0x01; - slot->reg_mult = data & 0x0f; -} - -static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data) -{ - slot->reg_ksl = (data >> 6) & 0x03; - slot->reg_tl = data & 0x3f; - OPL3_EnvelopeUpdateKSL(slot); -} - -static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data) -{ - slot->reg_ar = (data >> 4) & 0x0f; - slot->reg_dr = data & 0x0f; -} - -static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) -{ - slot->reg_sl = (data >> 4) & 0x0f; - if (slot->reg_sl == 0x0f) - { - slot->reg_sl = 0x1f; - } - slot->reg_rr = data & 0x0f; -} - -static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) -{ - slot->reg_wf = data & 0x07; - if (slot->chip->newm == 0x00) - { - slot->reg_wf &= 0x03; - } -} - -static void OPL3_SlotGenerate(opl3_slot *slot) -{ - slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out); -} - -static void OPL3_SlotCalcFB(opl3_slot *slot) -{ - if (slot->channel->fb != 0x00) - { - slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->channel->fb); - } - else - { - slot->fbmod = 0; - } - slot->prout = slot->out; -} - -// -// Channel -// - -static void OPL3_ChannelSetupAlg(opl3_channel *channel); - -static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) -{ - opl3_channel *channel6; - opl3_channel *channel7; - opl3_channel *channel8; - Bit8u chnum; - - chip->rhy = data & 0x3f; - if (chip->rhy & 0x20) - { - channel6 = &chip->channel[6]; - channel7 = &chip->channel[7]; - channel8 = &chip->channel[8]; - channel6->out[0] = &channel6->slots[1]->out; - channel6->out[1] = &channel6->slots[1]->out; - channel6->out[2] = &chip->zeromod; - channel6->out[3] = &chip->zeromod; - channel7->out[0] = &channel7->slots[0]->out; - channel7->out[1] = &channel7->slots[0]->out; - channel7->out[2] = &channel7->slots[1]->out; - channel7->out[3] = &channel7->slots[1]->out; - channel8->out[0] = &channel8->slots[0]->out; - channel8->out[1] = &channel8->slots[0]->out; - channel8->out[2] = &channel8->slots[1]->out; - channel8->out[3] = &channel8->slots[1]->out; - for (chnum = 6; chnum < 9; chnum++) - { - chip->channel[chnum].chtype = ch_drum; - } - OPL3_ChannelSetupAlg(channel6); - OPL3_ChannelSetupAlg(channel7); - OPL3_ChannelSetupAlg(channel8); - //hh - if (chip->rhy & 0x01) - { - OPL3_EnvelopeKeyOn(channel7->slots[0], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel7->slots[0], egk_drum); - } - //tc - if (chip->rhy & 0x02) - { - OPL3_EnvelopeKeyOn(channel8->slots[1], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel8->slots[1], egk_drum); - } - //tom - if (chip->rhy & 0x04) - { - OPL3_EnvelopeKeyOn(channel8->slots[0], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel8->slots[0], egk_drum); - } - //sd - if (chip->rhy & 0x08) - { - OPL3_EnvelopeKeyOn(channel7->slots[1], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel7->slots[1], egk_drum); - } - //bd - if (chip->rhy & 0x10) - { - OPL3_EnvelopeKeyOn(channel6->slots[0], egk_drum); - OPL3_EnvelopeKeyOn(channel6->slots[1], egk_drum); - } - else - { - OPL3_EnvelopeKeyOff(channel6->slots[0], egk_drum); - OPL3_EnvelopeKeyOff(channel6->slots[1], egk_drum); - } - } - else - { - for (chnum = 6; chnum < 9; chnum++) - { - chip->channel[chnum].chtype = ch_2op; - OPL3_ChannelSetupAlg(&chip->channel[chnum]); - OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[0], egk_drum); - OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[1], egk_drum); - } - } -} - -static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) -{ - if (channel->chip->newm && channel->chtype == ch_4op2) - { - return; - } - channel->f_num = (channel->f_num & 0x300) | data; - channel->ksv = (channel->block << 1) - | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); - OPL3_EnvelopeUpdateKSL(channel->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->slots[1]); - if (channel->chip->newm && channel->chtype == ch_4op) - { - channel->pair->f_num = channel->f_num; - channel->pair->ksv = channel->ksv; - OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - } -} - -static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) -{ - if (channel->chip->newm && channel->chtype == ch_4op2) - { - return; - } - channel->f_num = (channel->f_num & 0xff) | ((data & 0x03) << 8); - channel->block = (data >> 2) & 0x07; - channel->ksv = (channel->block << 1) - | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); - OPL3_EnvelopeUpdateKSL(channel->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->slots[1]); - if (channel->chip->newm && channel->chtype == ch_4op) - { - channel->pair->f_num = channel->f_num; - channel->pair->block = channel->block; - channel->pair->ksv = channel->ksv; - OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); - OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - } -} - -static void OPL3_ChannelSetupAlg(opl3_channel *channel) -{ - if (channel->chtype == ch_drum) - { - if (channel->ch_num == 7 || channel->ch_num == 8) - { - channel->slots[0]->mod = &channel->chip->zeromod; - channel->slots[1]->mod = &channel->chip->zeromod; - return; - } - switch (channel->alg & 0x01) - { - case 0x00: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->slots[0]->out; - break; - case 0x01: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->chip->zeromod; - break; - } - return; - } - if (channel->alg & 0x08) - { - return; - } - if (channel->alg & 0x04) - { - channel->pair->out[0] = &channel->chip->zeromod; - channel->pair->out[1] = &channel->chip->zeromod; - channel->pair->out[2] = &channel->chip->zeromod; - channel->pair->out[3] = &channel->chip->zeromod; - switch (channel->alg & 0x03) - { - case 0x00: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->slots[1]->out; - channel->out[1] = &channel->chip->zeromod; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - case 0x01: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->pair->slots[0]->out; - channel->slots[0]->mod = &channel->chip->zeromod; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->pair->slots[1]->out; - channel->out[1] = &channel->slots[1]->out; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - case 0x02: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->chip->zeromod; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->pair->slots[0]->out; - channel->out[1] = &channel->slots[1]->out; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - case 0x03: - channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod; - channel->pair->slots[1]->mod = &channel->chip->zeromod; - channel->slots[0]->mod = &channel->pair->slots[1]->out; - channel->slots[1]->mod = &channel->chip->zeromod; - channel->out[0] = &channel->pair->slots[0]->out; - channel->out[1] = &channel->slots[0]->out; - channel->out[2] = &channel->slots[1]->out; - channel->out[3] = &channel->chip->zeromod; - break; - } - } - else - { - switch (channel->alg & 0x01) - { - case 0x00: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->slots[0]->out; - channel->out[0] = &channel->slots[1]->out; - channel->out[1] = &channel->chip->zeromod; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - case 0x01: - channel->slots[0]->mod = &channel->slots[0]->fbmod; - channel->slots[1]->mod = &channel->chip->zeromod; - channel->out[0] = &channel->slots[0]->out; - channel->out[1] = &channel->slots[1]->out; - channel->out[2] = &channel->chip->zeromod; - channel->out[3] = &channel->chip->zeromod; - break; - } - } -} - -static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) -{ - channel->fb = (data & 0x0e) >> 1; - channel->con = data & 0x01; - channel->alg = channel->con; - if (channel->chip->newm) - { - if (channel->chtype == ch_4op) - { - channel->pair->alg = 0x04 | (channel->con << 1) | (channel->pair->con); - channel->alg = 0x08; - OPL3_ChannelSetupAlg(channel->pair); - } - else if (channel->chtype == ch_4op2) - { - channel->alg = 0x04 | (channel->pair->con << 1) | (channel->con); - channel->pair->alg = 0x08; - OPL3_ChannelSetupAlg(channel); - } - else - { - OPL3_ChannelSetupAlg(channel); - } - } - else - { - OPL3_ChannelSetupAlg(channel); - } - if (channel->chip->newm) - { - channel->cha = ((data >> 4) & 0x01) ? ~0 : 0; - channel->chb = ((data >> 5) & 0x01) ? ~0 : 0; - } - else - { - channel->cha = channel->chb = (Bit16u)~0; - } - if (!channel->chip->stereoext) - { - channel->leftpan = channel->cha << 16; - channel->rightpan = channel->chb << 16; - } -} - -static void OPL3_ChannelWriteD0(opl3_channel* channel, Bit8u data) -{ - if (channel->chip->stereoext) - { - channel->leftpan = panpot_lut[data ^ 0xff]; - channel->rightpan = panpot_lut[data]; - } -} - -static void OPL3_ChannelKeyOn(opl3_channel *channel) -{ - if (channel->chip->newm) - { - if (channel->chtype == ch_4op) - { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); - OPL3_EnvelopeKeyOn(channel->pair->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->pair->slots[1], egk_norm); - } - else if (channel->chtype == ch_2op || channel->chtype == ch_drum) - { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); - } - } - else - { - OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm); - } -} - -static void OPL3_ChannelKeyOff(opl3_channel *channel) -{ - if (channel->chip->newm) - { - if (channel->chtype == ch_4op) - { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); - OPL3_EnvelopeKeyOff(channel->pair->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->pair->slots[1], egk_norm); - } - else if (channel->chtype == ch_2op || channel->chtype == ch_drum) - { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); - } - } - else - { - OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm); - OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm); - } -} - -static void OPL3_ChannelSet4Op(opl3_chip *chip, Bit8u data) -{ - Bit8u bit; - Bit8u chnum; - for (bit = 0; bit < 6; bit++) - { - chnum = bit; - if (bit >= 3) - { - chnum += 9 - 3; - } - if ((data >> bit) & 0x01) - { - chip->channel[chnum].chtype = ch_4op; - chip->channel[chnum + 3].chtype = ch_4op2; - } - else - { - chip->channel[chnum].chtype = ch_2op; - chip->channel[chnum + 3].chtype = ch_2op; - } - } -} - -static Bit16s OPL3_ClipSample(Bit32s sample) -{ - if (sample > 32767) - { - sample = 32767; - } - else if (sample < -32768) - { - sample = -32768; - } - return (Bit16s)sample; -} - -void OPL3_Generate(opl3_chip *chip, Bit16s *buf) -{ - Bit8u ii; - Bit8u jj; - Bit16s accm; - Bit8u shift = 0; - - buf[1] = OPL3_ClipSample(chip->mixbuff[1]); - - for (ii = 0; ii < 36; ii++) - { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_SlotGenerate(&chip->slot[ii]); - } - - chip->mixbuff[0] = 0; - for (ii = 0; ii < 18; ii++) - { - accm = 0; - for (jj = 0; jj < 4; jj++) - { - accm += *chip->channel[ii].out[jj]; - } - chip->mixbuff[0] += (Bit16s)((accm * chip->channel[ii].leftpan) >> 16); - } - - buf[0] = OPL3_ClipSample(chip->mixbuff[0]); - - chip->mixbuff[1] = 0; - for (ii = 0; ii < 18; ii++) - { - accm = 0; - for (jj = 0; jj < 4; jj++) - { - accm += *chip->channel[ii].out[jj]; - } - chip->mixbuff[1] += (Bit16s)((accm * chip->channel[ii].rightpan) >> 16); - } - - if ((chip->timer & 0x3f) == 0x3f) - { - chip->tremolopos = (chip->tremolopos + 1) % 210; - } - if (chip->tremolopos < 105) - { - chip->tremolo = chip->tremolopos >> chip->tremoloshift; - } - else - { - chip->tremolo = (210 - chip->tremolopos) >> chip->tremoloshift; - } - - if ((chip->timer & 0x3ff) == 0x3ff) - { - chip->vibpos = (chip->vibpos + 1) & 7; - } - - chip->timer++; - - chip->eg_add = 0; - if (chip->eg_timer) - { - while (shift < 36 && ((chip->eg_timer >> shift) & 1) == 0) - { - shift++; - } - if (shift > 12) - { - chip->eg_add = 0; - } - else - { - chip->eg_add = shift + 1; - } - } - - if (chip->eg_timerrem || chip->eg_state) - { - if (chip->eg_timer == 0xfffffffff) - { - chip->eg_timer = 0; - chip->eg_timerrem = 1; - } - else - { - chip->eg_timer++; - chip->eg_timerrem = 0; - } - } - - chip->eg_state ^= 1; - - while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt) - { - if (!(chip->writebuf[chip->writebuf_cur].reg & 0x200)) - { - break; - } - chip->writebuf[chip->writebuf_cur].reg &= 0x1ff; - OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg, - chip->writebuf[chip->writebuf_cur].data); - chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE; - } - chip->writebuf_samplecnt++; -} - -void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) -{ - while (chip->samplecnt >= chip->rateratio) - { - chip->oldsamples[0] = chip->samples[0]; - chip->oldsamples[1] = chip->samples[1]; - OPL3_Generate(chip, chip->samples); - chip->samplecnt -= chip->rateratio; - } - buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) - + chip->samples[0] * chip->samplecnt) / chip->rateratio); - buf[1] = (Bit16s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) - + chip->samples[1] * chip->samplecnt) / chip->rateratio); - chip->samplecnt += 1 << RSM_FRAC; -} - -void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) -{ - Bit8u slotnum; - Bit8u channum; - - memset(chip, 0, sizeof(opl3_chip)); - for (slotnum = 0; slotnum < 36; slotnum++) - { - chip->slot[slotnum].chip = chip; - chip->slot[slotnum].mod = &chip->zeromod; - chip->slot[slotnum].eg_rout = 0x1ff; - chip->slot[slotnum].eg_out = 0x1ff; - chip->slot[slotnum].eg_gen = envelope_gen_num_release; - chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod; - chip->slot[slotnum].slot_num = slotnum; - } - for (channum = 0; channum < 18; channum++) - { - chip->channel[channum].slots[0] = &chip->slot[ch_slot[channum]]; - chip->channel[channum].slots[1] = &chip->slot[ch_slot[channum] + 3]; - chip->slot[ch_slot[channum]].channel = &chip->channel[channum]; - chip->slot[ch_slot[channum] + 3].channel = &chip->channel[channum]; - if ((channum % 9) < 3) - { - chip->channel[channum].pair = &chip->channel[channum + 3]; - } - else if ((channum % 9) < 6) - { - chip->channel[channum].pair = &chip->channel[channum - 3]; - } - chip->channel[channum].chip = chip; - chip->channel[channum].out[0] = &chip->zeromod; - chip->channel[channum].out[1] = &chip->zeromod; - chip->channel[channum].out[2] = &chip->zeromod; - chip->channel[channum].out[3] = &chip->zeromod; - chip->channel[channum].chtype = ch_2op; - chip->channel[channum].cha = 0xffff; - chip->channel[channum].chb = 0xffff; - chip->channel[channum].leftpan = 0x10000; - chip->channel[channum].rightpan = 0x10000; - chip->channel[channum].ch_num = channum; - OPL3_ChannelSetupAlg(&chip->channel[channum]); - } - chip->noise = 1; - chip->rateratio = (samplerate << RSM_FRAC) / 49716; - chip->tremoloshift = 4; - chip->vibshift = 1; - - if (!panpot_lut_build) - { - for (int i = 0; i < 256; i++) - { - panpot_lut[i] = (Bit32u)(sin(i * M_PI / 512.0) * 0x10000); - } - panpot_lut_build = 1; - } -} - -void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) -{ - Bit8u high = (reg >> 8) & 0x01; - Bit8u regm = reg & 0xff; - switch (regm & 0xf0) - { - case 0x00: - if (high) - { - switch (regm & 0x0f) - { - case 0x04: - OPL3_ChannelSet4Op(chip, v); - break; - case 0x05: - chip->newm = v & 0x01; - chip->stereoext = (v >> 1) & 0x01; - break; - } - } - else - { - switch (regm & 0x0f) - { - case 0x08: - chip->nts = (v >> 6) & 0x01; - break; - } - } - break; - case 0x20: - case 0x30: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWrite20(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0x40: - case 0x50: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWrite40(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0x60: - case 0x70: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWrite60(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0x80: - case 0x90: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWrite80(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0xe0: - case 0xf0: - if (ad_slot[regm & 0x1f] >= 0) - { - OPL3_SlotWriteE0(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v); - } - break; - case 0xa0: - if ((regm & 0x0f) < 9) - { - OPL3_ChannelWriteA0(&chip->channel[9 * high + (regm & 0x0f)], v); - } - break; - case 0xb0: - if (regm == 0xbd && !high) - { - chip->tremoloshift = (((v >> 7) ^ 1) << 1) + 2; - chip->vibshift = ((v >> 6) & 0x01) ^ 1; - OPL3_ChannelUpdateRhythm(chip, v); - } - else if ((regm & 0x0f) < 9) - { - OPL3_ChannelWriteB0(&chip->channel[9 * high + (regm & 0x0f)], v); - if (v & 0x20) - { - OPL3_ChannelKeyOn(&chip->channel[9 * high + (regm & 0x0f)]); - } - else - { - OPL3_ChannelKeyOff(&chip->channel[9 * high + (regm & 0x0f)]); - } - } - break; - case 0xc0: - if ((regm & 0x0f) < 9) - { - OPL3_ChannelWriteC0(&chip->channel[9 * high + (regm & 0x0f)], v); - } - break; - case 0xd0: - if ((regm & 0x0f) < 9) - { - OPL3_ChannelWriteD0(&chip->channel[9 * high + (regm & 0x0f)], v); - } - break; - } -} - -void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) -{ - Bit64u time1, time2; - - if (chip->writebuf[chip->writebuf_last].reg & 0x200) - { - OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, - chip->writebuf[chip->writebuf_last].data); - - chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; - chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time; - } - - chip->writebuf[chip->writebuf_last].reg = reg | 0x200; - chip->writebuf[chip->writebuf_last].data = v; - time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY; - time2 = chip->writebuf_samplecnt; - - if (time1 < time2) - { - time1 = time2; - } - - chip->writebuf[chip->writebuf_last].time = time1; - chip->writebuf_lasttime = time1; - chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; -} - -void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) -{ - Bit32u i; - - for(i = 0; i < numsamples; i++) - { - OPL3_GenerateResampled(chip, sndptr); - sndptr += 2; - } -} diff --git a/source/audiolib/src/pitch.cpp b/source/audiolib/src/pitch.cpp deleted file mode 100644 index d4f9e75ab..000000000 --- a/source/audiolib/src/pitch.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -/********************************************************************** - module: PITCH.C - - author: James R. Dose - date: June 14, 1993 - - Routines for pitch scaling. - - (c) Copyright 1993 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#include "compat.h" -#include "pitch.h" - -#define MAXDETUNE 50 - -static uint32_t PitchTable[12][MAXDETUNE]; - - -/*--------------------------------------------------------------------- - Function: PITCH_Init - - Initializes pitch table. ----------------------------------------------------------------------*/ - - -void PITCH_Init(void) -{ - for (int note = 0; note < 12; note++) - for (int detune = 0; detune < MAXDETUNE; detune++) - PitchTable[note][detune] = (uint32_t) (65536.f * powf(2.f, (note * MAXDETUNE + detune) / (12.f * MAXDETUNE))); -} - - -/*--------------------------------------------------------------------- - Function: PITCH_GetScale - - Returns a fixed-point value to scale number the specified amount. ----------------------------------------------------------------------*/ - -uint32_t PITCH_GetScale(int const pitchoffset) -{ - static bool bInitialized; - - if (!bInitialized) - { - PITCH_Init(); - bInitialized = true; - } - - if (pitchoffset == 0) - return PitchTable[0][0]; - - int noteshift = pitchoffset % 1200; - - if (noteshift < 0) - noteshift += 1200; - - int const note = noteshift / 100; - int const detune = (noteshift % 100) / (100 / MAXDETUNE); - int const oshift = (pitchoffset - noteshift) / 1200; - auto const &scale = PitchTable[note][detune]; - - return (oshift < 0) ? (scale >> -oshift) : (scale << oshift); -} diff --git a/source/audiolib/src/pitch.h b/source/audiolib/src/pitch.h deleted file mode 100644 index 9b81e68f2..000000000 --- a/source/audiolib/src/pitch.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright (C) 1994-1995 Apogee Software, Ltd. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -/********************************************************************** - module: PITCH.H - - author: James R. Dose - date: June 14, 1994 - - Public header for PITCH.C - - (c) Copyright 1994 James R. Dose. All Rights Reserved. -**********************************************************************/ - -#ifndef PITCH_H_ -#define PITCH_H_ - -#include - -uint32_t PITCH_GetScale(int pitchoffset); -#endif diff --git a/source/audiolib/src/vorbis.cpp b/source/audiolib/src/vorbis.cpp deleted file mode 100644 index e095b055e..000000000 --- a/source/audiolib/src/vorbis.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/* - Copyright (C) 2009 Jonathon Fowler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - */ - -/** - * OggVorbis source support for MultiVoc - */ - -#include "compat.h" -#include "pragmas.h" - -#ifdef HAVE_VORBIS - -#include "pitch.h" -#include "multivoc.h" -#include "_multivc.h" - -#define OV_EXCLUDE_STATIC_CALLBACKS - -#if defined __APPLE__ -# include -#elif defined GEKKO -# define USING_TREMOR -# include -#else -# include "vorbis/vorbisfile.h" -#endif - -#define BLOCKSIZE MV_MIXBUFFERSIZE - - -typedef struct { - void * ptr; - size_t length; - size_t pos; - - OggVorbis_File vf; - - char block[BLOCKSIZE]; - int lastbitstream; -} vorbis_data; - -// designed with multiple calls in mind -static void MV_GetVorbisCommentLoops(VoiceNode *voice, vorbis_comment *vc) -{ - const char *vc_loopstart = nullptr; - const char *vc_loopend = nullptr; - const char *vc_looplength = nullptr; - - for (int comment = 0; comment < vc->comments; ++comment) - { - auto entry = (const char *)vc->user_comments[comment]; - if (entry != nullptr && entry[0] != '\0') - { - const char *value = Bstrchr(entry, '='); - - if (!value) - continue; - - const size_t field = value - entry; - value += 1; - - for (int t = 0; t < loopStartTagCount && vc_loopstart == nullptr; ++t) - { - auto tag = loopStartTags[t]; - if (field == Bstrlen(tag) && Bstrncasecmp(entry, tag, field) == 0) - vc_loopstart = value; - } - - for (int t = 0; t < loopEndTagCount && vc_loopend == nullptr; ++t) - { - auto tag = loopEndTags[t]; - if (field == Bstrlen(tag) && Bstrncasecmp(entry, tag, field) == 0) - vc_loopend = value; - } - - for (int t = 0; t < loopLengthTagCount && vc_looplength == nullptr; ++t) - { - auto tag = loopLengthTags[t]; - if (field == Bstrlen(tag) && Bstrncasecmp(entry, tag, field) == 0) - vc_looplength = value; - } - } - } - - if (vc_loopstart != nullptr) - { - const ogg_int64_t ov_loopstart = Batol(vc_loopstart); - if (ov_loopstart >= 0) // a loop starting at 0 is valid - { - voice->LoopStart = (const char *) (intptr_t) ov_loopstart; - voice->LoopSize = 1; - } - } - if (vc_loopend != nullptr) - { - if (voice->LoopSize > 0) - { - const ogg_int64_t ov_loopend = Batol(vc_loopend); - if (ov_loopend > 0) // a loop ending at 0 is invalid - voice->LoopEnd = (const char *) (intptr_t) ov_loopend; - } - } - if (vc_looplength != nullptr) - { - if (voice->LoopSize > 0 && voice->LoopEnd == 0) - { - const ogg_int64_t ov_looplength = Batol(vc_looplength); - if (ov_looplength > 0) // a loop of length 0 is invalid - voice->LoopEnd = (const char *) ((intptr_t) ov_looplength + (intptr_t) voice->LoopStart); - } - } -} - -// callbacks - -static size_t read_vorbis(void *ptr, size_t size, size_t nmemb, void *datasource) -{ - auto vorb = (vorbis_data *)datasource; - - errno = 0; - - if (vorb->length == vorb->pos) - return 0; - - int nread = 0; - - for (; nmemb > 0; nmemb--, nread++) - { - int bytes = vorb->length - vorb->pos; - - if ((signed)size < bytes) - bytes = (int)size; - - memcpy(ptr, (uint8_t *)vorb->ptr + vorb->pos, bytes); - vorb->pos += bytes; - ptr = (uint8_t *)ptr + bytes; - - if (vorb->length == vorb->pos) - { - nread++; - break; - } - } - - return nread; -} - - -static int seek_vorbis(void *datasource, ogg_int64_t offset, int whence) -{ - auto vorb = (vorbis_data *)datasource; - - switch (whence) - { - case SEEK_SET: vorb->pos = 0; break; - case SEEK_CUR: break; - case SEEK_END: vorb->pos = vorb->length; break; - } - - vorb->pos += offset; - - if (vorb->pos > vorb->length) - vorb->pos = vorb->length; - - return vorb->pos; -} - -static int close_vorbis(void *datasource) -{ - UNREFERENCED_PARAMETER(datasource); - return 0; -} - -static long tell_vorbis(void *datasource) -{ - auto vorb = (vorbis_data *)datasource; - - return vorb->pos; -} - -static ov_callbacks vorbis_callbacks = { read_vorbis, seek_vorbis, close_vorbis, tell_vorbis }; - - -int MV_GetVorbisPosition(VoiceNode *voice) -{ - auto vd = (vorbis_data *) voice->rawdataptr; - - return ov_pcm_tell(&vd->vf); -} - -void MV_SetVorbisPosition(VoiceNode *voice, int position) -{ - auto vd = (vorbis_data *) voice->rawdataptr; - - ov_pcm_seek(&vd->vf, position); -} - -/*--------------------------------------------------------------------- -Function: MV_GetNextVorbisBlock - -Controls playback of OggVorbis data ----------------------------------------------------------------------*/ - -static playbackstatus MV_GetNextVorbisBlock(VoiceNode *voice) -{ - int bitstream; - - int bytesread = 0; - auto vd = (vorbis_data *)voice->rawdataptr; - do - { -#ifdef USING_TREMOR - int bytes = ov_read(&vd->vf, vd->block + bytesread, BLOCKSIZE - bytesread, &bitstream); -#else - int bytes = ov_read(&vd->vf, vd->block + bytesread, BLOCKSIZE - bytesread, 0, 2, 1, &bitstream); -#endif - // fprintf(stderr, "ov_read = %d\n", bytes); - if (bytes > 0) - { - ogg_int64_t currentPosition; - bytesread += bytes; - if ((ogg_int64_t)(intptr_t)voice->LoopEnd > 0 && - (currentPosition = ov_pcm_tell(&vd->vf)) >= (ogg_int64_t)(intptr_t)voice->LoopEnd) - { - bytesread -= - (currentPosition - (ogg_int64_t)(intptr_t)voice->LoopEnd) * voice->channels * 2; // (voice->bits>>3) - - int const err = ov_pcm_seek(&vd->vf, (ogg_int64_t)(intptr_t)voice->LoopStart); - - if (err != 0) - { - MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, LOOP_END %l, err %d\n", - (ogg_int64_t)(intptr_t)voice->LoopStart, (ogg_int64_t)(intptr_t)voice->LoopEnd, err); - } - } - continue; - } - else if (bytes == OV_HOLE) - continue; - else if (bytes == 0) - { - if (voice->LoopSize > 0) - { - int const err = ov_pcm_seek(&vd->vf, (ogg_int64_t)(intptr_t)voice->LoopStart); - - if (err != 0) - { - MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, err %d\n", - (ogg_int64_t)(intptr_t)voice->LoopStart, err); - } - else - continue; - } - else - { - break; - } - } - else if (bytes < 0) - { - MV_Printf("MV_GetNextVorbisBlock ov_read: err %d\n", bytes); - return NoMoreData; - } - } while (bytesread < BLOCKSIZE); - - if (bytesread == 0) - return NoMoreData; - - if (bitstream != vd->lastbitstream) - { - vorbis_info *vi = ov_info(&vd->vf, -1); - if (!vi || (vi->channels != 1 && vi->channels != 2)) - return NoMoreData; - - voice->channels = vi->channels; - voice->SamplingRate = vi->rate; - voice->RateScale = divideu32(voice->SamplingRate * voice->PitchScale, MV_MixRate); - - voice->FixedPointBufferSize = (voice->RateScale * MV_MIXBUFFERSIZE) - voice->RateScale; - vd->lastbitstream = bitstream; - MV_SetVoiceMixMode(voice); - } - - uint32_t const samples = divideu32(bytesread, ((voice->bits>>3) * voice->channels)); - - voice->position = 0; - voice->sound = vd->block; - voice->BlockLength = 0; - voice->length = samples << 16; - -#ifdef GEKKO - // If libtremor had the three additional ov_read() parameters that libvorbis has, - // this would be better handled using the endianness parameter. - int16_t *data = (int16_t *)(vd->block); // assumes signed 16-bit - for (bytesread = 0; bytesread < BLOCKSIZE / 2; ++bytesread) - data[bytesread] = (data[bytesread] & 0xff) << 8 | ((data[bytesread] & 0xff00) >> 8); -#endif - - return KeepPlaying; -} - - -/*--------------------------------------------------------------------- -Function: MV_PlayVorbis3D - -Begin playback of sound data at specified angle and distance -from listener. ----------------------------------------------------------------------*/ - -int MV_PlayVorbis3D(char *ptr, uint32_t length, int loophow, int pitchoffset, int angle, int distance, int priority, float volume, intptr_t callbackval) -{ - if (!MV_Installed) - return MV_SetErrorCode(MV_NotInstalled); - - if (distance < 0) - { - distance = -distance; - angle += MV_NUMPANPOSITIONS / 2; - } - - int const vol = MIX_VOLUME(distance); - - // Ensure angle is within 0 - 127 - angle &= MV_MAXPANPOSITION; - - return MV_PlayVorbis(ptr, length, loophow, -1, pitchoffset, max(0, 255 - distance), - MV_PanTable[angle][vol].left, MV_PanTable[angle][vol].right, priority, volume, callbackval); -} - - -/*--------------------------------------------------------------------- -Function: MV_PlayVorbis - -Begin playback of sound data with the given sound levels and -priority. ----------------------------------------------------------------------*/ - -int MV_PlayVorbis(char *ptr, uint32_t length, int loopstart, int loopend, int pitchoffset, int vol, int left, int right, int priority, float volume, intptr_t callbackval) -{ - UNREFERENCED_PARAMETER(loopend); - - if (!MV_Installed) - return MV_SetErrorCode(MV_NotInstalled); - - VoiceNode *voice = MV_AllocVoice(priority); - - if (voice == nullptr) - return MV_SetErrorCode(MV_NoVoices); - - - auto vd = (vorbis_data *)Xcalloc(1, sizeof(vorbis_data)); - vd->ptr = ptr; - vd->pos = 0; - vd->length = length; - - vd->lastbitstream = -1; - - int status = ov_open_callbacks((void *)vd, &vd->vf, 0, 0, vorbis_callbacks); - vorbis_info *vi; - - if (status < 0 || ((vi = ov_info(&vd->vf, 0)) == nullptr) || vi->channels < 1 || vi->channels > 2) - { - if (status == 0) - ov_clear(&vd->vf); - else - MV_Printf("MV_PlayVorbis: err %d\n", status); - - Xfree(vd); - return MV_SetErrorCode(MV_InvalidFile); - } - - voice->wavetype = FMT_VORBIS; - voice->bits = 16; - voice->channels = vi->channels; - voice->rawdataptr = (void *)vd; - voice->GetSound = MV_GetNextVorbisBlock; - voice->NextBlock = vd->block; - voice->LoopCount = 0; - voice->BlockLength = 0; - voice->length = 0; - voice->next = nullptr; - voice->prev = nullptr; - voice->priority = priority; - voice->callbackval = callbackval; - - voice->LoopStart = nullptr; - voice->LoopEnd = nullptr; - voice->LoopSize = (loopstart >= 0 ? 1 : 0); - - // load loop tags from metadata - if (auto comment = ov_comment(&vd->vf, 0)) - MV_GetVorbisCommentLoops(voice, comment); - - voice->Paused = FALSE; - - MV_SetVoicePitch(voice, vi->rate, pitchoffset); - MV_SetVoiceMixMode(voice); - - MV_SetVoiceVolume(voice, vol, left, right, volume); - MV_PlayVoice(voice); - - return voice->handle; -} - -void MV_ReleaseVorbisVoice( VoiceNode * voice ) -{ - if (voice->wavetype != FMT_VORBIS) - return; - - auto vd = (vorbis_data *)voice->rawdataptr; - - voice->length = 0; - voice->sound = nullptr; - ov_clear(&vd->vf); - Xfree(vd); -} -#else -#include "_multivc.h" - -int MV_PlayVorbis(char *ptr, uint32_t ptrlength, int loopstart, int loopend, int pitchoffset, - int vol, int left, int right, int priority, float volume, intptr_t callbackval) -{ - UNREFERENCED_PARAMETER(ptr); - UNREFERENCED_PARAMETER(ptrlength); - UNREFERENCED_PARAMETER(loopstart); - UNREFERENCED_PARAMETER(loopend); - UNREFERENCED_PARAMETER(pitchoffset); - UNREFERENCED_PARAMETER(vol); - UNREFERENCED_PARAMETER(left); - UNREFERENCED_PARAMETER(right); - UNREFERENCED_PARAMETER(priority); - UNREFERENCED_PARAMETER(volume); - UNREFERENCED_PARAMETER(callbackval); - - MV_Printf("MV_PlayVorbis: OggVorbis support not included in this binary.\n"); - return -1; -} - -int MV_PlayVorbis3D(char *ptr, uint32_t ptrlength, int loophow, int pitchoffset, int angle, - int distance, int priority, float volume, intptr_t callbackval) -{ - UNREFERENCED_PARAMETER(ptr); - UNREFERENCED_PARAMETER(ptrlength); - UNREFERENCED_PARAMETER(loophow); - UNREFERENCED_PARAMETER(pitchoffset); - UNREFERENCED_PARAMETER(angle); - UNREFERENCED_PARAMETER(distance); - UNREFERENCED_PARAMETER(priority); - UNREFERENCED_PARAMETER(volume); - UNREFERENCED_PARAMETER(callbackval); - - MV_Printf("MV_PlayVorbis: OggVorbis support not included in this binary.\n"); - return -1; -} -#endif //HAVE_VORBIS diff --git a/source/blood/CMakeLists.txt b/source/blood/CMakeLists.txt index 564c2a255..7c9968e24 100644 --- a/source/blood/CMakeLists.txt +++ b/source/blood/CMakeLists.txt @@ -7,14 +7,13 @@ endif() include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/../../build/include" ) if (WIN32) - include_directories( "${ZLIB_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/vpx" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/sdl2") + include_directories( "${ZLIB_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/vpx" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/sdl2") else () -include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GDTOA_INCLUDE_DIR}") +include_directories( "${ZLIB_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GDTOA_INCLUDE_DIR}") endif() include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../build/include - ${CMAKE_CURRENT_SOURCE_DIR}/../mact/include ${CMAKE_CURRENT_SOURCE_DIR}/../audiolib/include ${CMAKE_CURRENT_SOURCE_DIR}/../libsmackerdec/include ${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/include @@ -25,6 +24,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../common/fonts ${CMAKE_CURRENT_SOURCE_DIR}/../common/2d ${CMAKE_CURRENT_SOURCE_DIR}/../common/music + ${CMAKE_CURRENT_SOURCE_DIR}/../common/input ${CMAKE_CURRENT_SOURCE_DIR}/../platform ) diff --git a/source/blood/src/ai.cpp b/source/blood/src/ai.cpp index 75ab9ab5f..ab99b6e35 100644 --- a/source/blood/src/ai.cpp +++ b/source/blood/src/ai.cpp @@ -950,7 +950,7 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T evKill(nSprite, 3, kCallbackFXFlameLick); } break; - case kDudeInnocent: // innocent + case kDudeInnocent: if (nDmgType == DAMAGE_TYPE_1 && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) { pSprite->type = kDudeBurningInnocent; @@ -993,12 +993,10 @@ int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_T evKill(nSprite, 3, kCallbackFXFlameLick); } break; - case kDudeTinyCaleb: // tiny Caleb + case kDudeTinyCaleb: if (nDmgType == DAMAGE_TYPE_1 && pXSprite->health <= (unsigned int)pDudeInfo->fleeHealth/* && (pXSprite->at17_6 != 1 || pXSprite->at17_6 != 2)*/) { pSprite->type = kDudeBurningInnocent; - if (!VanillaMode()) - pXSprite->scale = 64; aiNewState(pSprite, pXSprite, &cultistBurnGoto); aiPlay3DSound(pSprite, 361, AI_SFX_PRIORITY_0, -1); gDudeExtra[pSprite->extra].at0 = (int)gFrameClock+360; diff --git a/source/blood/src/aiunicult.cpp b/source/blood/src/aiunicult.cpp index c81d69b17..a45377787 100644 --- a/source/blood/src/aiunicult.cpp +++ b/source/blood/src/aiunicult.cpp @@ -48,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "endgame.h" #include "view.h" #include "tile.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS static void genDudeAttack1(int, int); @@ -902,6 +903,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt) { // let's check if there same sounds already played by other dudes // so we won't get a lot of annoying screams in the same time and ensure sound played in it's full length (if not interruptable) if (pExtra->sndPlaying && !sndInfo->interruptable) { +#if 0 for (int i = 0; i < 256; i++) { if (Bonkle[i].atc <= 0) continue; for (int a = 0; a < rand; a++) { @@ -915,6 +917,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt) { } } } +#endif pExtra->sndPlaying = false; @@ -928,7 +931,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt) { int maxRetries = 5; while (maxRetries-- > 0) { int random = Random(rand); - if (!gSoundRes.Lookup(sndId + random, "SFX")) continue; + if (!soundEngine->FindSoundByResID(sndId + random)) continue; sndId = sndId + random; gotSnd = true; break; @@ -938,7 +941,7 @@ bool playGenDudeSound(spritetype* pSprite, int mode, bool forceInterrupt) { if (gotSnd == false) { int maxSndId = sndId + rand; while (sndId++ <= maxSndId) { - if (!gSoundRes.Lookup(sndId, "SFX")) continue; + if (!soundEngine->FindSoundByResID(sndId)) continue; gotSnd = true; break; } diff --git a/source/blood/src/asound.cpp b/source/blood/src/asound.cpp index 0502732cb..938afb12c 100644 --- a/source/blood/src/asound.cpp +++ b/source/blood/src/asound.cpp @@ -24,7 +24,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "ns.h" // Must come before everything else! #include "build.h" -#include "fx_man.h" #include "common_game.h" //#include "blood.h" #include "view.h" @@ -33,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "player.h" #include "resource.h" #include "sound.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS @@ -40,13 +40,9 @@ BEGIN_BLD_NS struct AMB_CHANNEL { - int at0; - int at4; - int at8; - DICTNODE *atc; - char *at10; - int at14; - int at18; + FSoundID soundID; + int distance; + int check; }; AMB_CHANNEL ambChannels[kMaxAmbChannel]; @@ -75,22 +71,31 @@ void ambProcess(void) dz >>= 8; int nDist = ksqrt(dx*dx+dy*dy+dz*dz); int vs = mulscale16(pXSprite->data4, pXSprite->busy); - ambChannels[pSprite->owner].at4 += ClipRange(scale(nDist, pXSprite->data1, pXSprite->data2, vs, 0), 0, vs); + ambChannels[pSprite->owner].distance += ClipRange(scale(nDist, pXSprite->data1, pXSprite->data2, vs, 0), 0, vs); } } } AMB_CHANNEL *pChannel = ambChannels; for (int i = 0; i < nAmbChannels; i++, pChannel++) { - if (pChannel->at0 > 0) - FX_SetPan(pChannel->at0, pChannel->at4, pChannel->at4, pChannel->at4); - else + if (soundEngine->IsSourcePlayingSomething(SOURCE_Ambient, pChannel, CHAN_BODY, -1)) { - int end = ClipLow(pChannel->at14-1, 0); - pChannel->at0 = FX_PlayLoopedRaw(pChannel->at10, pChannel->at14, pChannel->at10, pChannel->at10+end, sndGetRate(pChannel->at18), 0, - pChannel->at4, pChannel->at4, pChannel->at4, pChannel->at4, 1.f, (intptr_t)&pChannel->at0); + if (pChannel->distance > 0) + { + soundEngine->ChangeSoundVolume(SOURCE_Ambient, pChannel, CHAN_BODY, pChannel->distance / 255.f); + } + else + { + // Stop the sound if it cannot be heard so that it doesn't occupy a physical channel. + soundEngine->StopSound(SOURCE_Ambient, pChannel, CHAN_BODY); + } } - pChannel->at4 = 0; + else if (pChannel->distance > 0) + { + FVector3 pt{}; + soundEngine->StartSound(SOURCE_Ambient, pChannel, &pt, CHAN_BODY, CHANF_LOOP, pChannel->soundID, pChannel->distance / 255.f, ATTN_NONE); + } + pChannel->distance = 0; } } @@ -99,16 +104,8 @@ void ambKillAll(void) AMB_CHANNEL *pChannel = ambChannels; for (int i = 0; i < nAmbChannels; i++, pChannel++) { - if (pChannel->at0 > 0) - { - FX_EndLooping(pChannel->at0); - FX_StopSound(pChannel->at0); - } - if (pChannel->atc) - { - gSoundRes.Unlock(pChannel->atc); - pChannel->atc = NULL; - } + soundEngine->StopSound(SOURCE_Ambient, pChannel, CHAN_BODY); + pChannel->soundID = 0; } nAmbChannels = 0; } @@ -125,7 +122,7 @@ void ambInit(void) int i; AMB_CHANNEL *pChannel = ambChannels; for (i = 0; i < nAmbChannels; i++, pChannel++) - if (pXSprite->data3 == pChannel->at8) break; + if (pXSprite->data3 == pChannel->check) break; if (i == nAmbChannels) { @@ -135,30 +132,17 @@ void ambInit(void) } int nSFX = pXSprite->data3; - DICTNODE *pSFXNode = gSoundRes.Lookup(nSFX, "SFX"); - if (!pSFXNode) { + auto snd = soundEngine->FindSoundByResID(nSFX); + if (!snd) { //ThrowError("Missing sound #%d used in ambient sound generator %d\n", nSFX); viewSetSystemMessage("Missing sound #%d used in ambient sound generator #%d\n", nSFX); continue; } - SFX *pSFX = (SFX*)gSoundRes.Load(pSFXNode); - DICTNODE *pRAWNode = gSoundRes.Lookup(pSFX->rawName, "RAW"); - if (!pRAWNode) { - //ThrowError("Missing RAW sound \"%s\" used in ambient sound generator %d\n", pSFX->rawName, nSFX); - viewSetSystemMessage("Missing RAW sound \"%s\" used in ambient sound generator %d\n", pSFX->rawName, nSFX); - continue; - } - - if (pRAWNode->Size() > 0) { - pChannel->at14 = pRAWNode->Size(); - pChannel->at8 = nSFX; - pChannel->atc = pRAWNode; - pChannel->at14 = pRAWNode->Size(); - pChannel->at10 = (char*)gSoundRes.Lock(pRAWNode); - pChannel->at18 = pSFX->format; - nAmbChannels++; - } + pChannel->soundID = FSoundID(snd); + pChannel->check = nSFX; + pChannel->distance = 0; + nAmbChannels++; } diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index 2bb26e7c9..66afe5ea4 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mmulti.h" #include "compat.h" #include "renderlayer.h" -#include "fx_man.h" #include "common.h" #include "common_game.h" @@ -50,7 +49,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "loadsave.h" #include "gamemenu.h" #include "mirrors.h" -#include "music.h" #include "network.h" #include "osdcmds.h" #include "replace.h" @@ -72,6 +70,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "m_argv.h" #include "statistics.h" #include "menu/menu.h" +#include "sound/s_soundinternal.h" #ifdef _WIN32 # include @@ -172,10 +171,9 @@ void ShutDown(void) if (!in3dmode()) return; netDeinitialize(); - sndTerm(); + //sndTerm(); sfxTerm(); scrUnInit(); - CONTROL_Shutdown(); // PORT_TODO: Check argument if (syncstate) printf("A packet was lost! (syncstate)\n"); @@ -403,8 +401,6 @@ void PreloadCache(void) if (r_precache) PrecacheHardwareTextures(i); #endif - MUSIC_Update(); - if ((++cnt & 7) == 0) gameHandleEvents(); @@ -916,7 +912,6 @@ void ProcessFrame(void) actProcessSprites(); actPostProcess(); viewCorrectPrediction(); - sndProcess(); ambProcess(); viewUpdateDelirium(); viewUpdateShake(); @@ -1140,7 +1135,6 @@ int GameInterface::app_main() #endif //gSysRes.Init(pUserRFF ? pUserRFF : "BLOOD.RFF"); //gGuiRes.Init("GUI.RFF"); - //gSoundRes.Init(pUserSoundRFF ? pUserSoundRFF : "SOUNDS.RFF"); HookReplaceFunctions(); @@ -1196,10 +1190,9 @@ int GameInterface::app_main() netInitialize(true); scrSetGameMode( ScreenMode, ScreenWidth, ScreenHeight, ScreenBPP); scrSetGamma(gGamma); - viewResizeView(gViewSize); + hud_size.Callback(); initprintf("Initializing sound system\n"); sndInit(); - sfxInit(); gChoke.sub_83ff0(518, sub_84230); if (bAddUserMap) { @@ -1252,7 +1245,6 @@ RESTART: { handleevents(); netUpdate(); - MUSIC_Update(); inputState.SetBindsEnabled(gInputMode == kInputGame); switch (gInputMode) { @@ -1368,7 +1360,7 @@ RESTART: { UpdateDacs(0, true); Mus_Stop(); - FX_StopAllSounds(); + soundEngine->StopAllChannels(); gQuitGame = 0; gQuitRequest = 0; gRestartGame = 0; @@ -1963,7 +1955,7 @@ int loaddefinitions_game(const char *fileName, int32_t firstPass) if (pScript) parsedefinitions_game(pScript, firstPass); - for (auto & m : *userConfig.AddDefs) + if (userConfig.AddDefs) for (auto & m : *userConfig.AddDefs) parsedefinitions_game_include(m, NULL, "null", firstPass); if (pScript) diff --git a/source/blood/src/common_game.h b/source/blood/src/common_game.h index e12eeb48f..07f0dec8c 100644 --- a/source/blood/src/common_game.h +++ b/source/blood/src/common_game.h @@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #pragma once #include "baselayer.h" #include "build.h" -#include "cache1d.h" + #include "common.h" #include "pragmas.h" #include "misc.h" diff --git a/source/blood/src/config.cpp b/source/blood/src/config.cpp index d0e9b7b45..286b98282 100644 --- a/source/blood/src/config.cpp +++ b/source/blood/src/config.cpp @@ -27,8 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "baselayer.h" #include "common_game.h" #include "build.h" -#include "cache1d.h" -#include "sndcards.h" + #include "hash.h" #include "renderlayer.h" #include "gamecontrol.h" @@ -53,7 +52,6 @@ BEGIN_BLD_NS int32_t gTurnSpeed; int32_t gDetail; int32_t cl_weaponswitch; -int32_t gAutoRun; int32_t gFollowMap; int32_t gOverlayMap; int32_t gRotateMap; @@ -105,7 +103,6 @@ void CONFIG_SetDefaults(void) gViewSize = 2; gTurnSpeed = 92; gDetail = 4; - gAutoRun = 0; gFollowMap = 1; gOverlayMap = 0; gRotateMap = 0; diff --git a/source/blood/src/config.h b/source/blood/src/config.h index da8cf0efd..da51e612b 100644 --- a/source/blood/src/config.h +++ b/source/blood/src/config.h @@ -24,9 +24,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef config_public_h_ #define config_public_h_ -#include "keyboard.h" -#include "control.h" -#include "_control.h" #include "hash.h" #include "gamecvars.h" #include "gamecontrol.h" @@ -37,7 +34,6 @@ BEGIN_BLD_NS extern int32_t gTurnSpeed; extern int32_t gDetail; -extern int32_t gAutoRun; extern int32_t gFollowMap; extern int32_t gOverlayMap; extern int32_t gRotateMap; diff --git a/source/blood/src/controls.cpp b/source/blood/src/controls.cpp index 4a85b6afe..558404b4b 100644 --- a/source/blood/src/controls.cpp +++ b/source/blood/src/controls.cpp @@ -25,10 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "baselayer.h" -#include "keyboard.h" -#include "mouse.h" -#include "joystick.h" -#include "control.h" #include "gamecontrol.h" #include "common_game.h" #include "blood.h" @@ -46,8 +42,8 @@ int32_t ctrlCheckAllInput(void) { return ( inputState.keyBufferWaiting() || - inputState.MouseGetButtons() || - JOYSTICK_GetButtons() + inputState.MouseGetButtons() + //JOYSTICK_GetButtons() ); } @@ -56,7 +52,8 @@ void ctrlClearAllInput(void) inputState.keyFlushChars(); inputState.ClearKeysDown(); inputState.MouseClearAllButtonss(); - JOYSTICK_ClearAllButtons(); + //JOYSTICK_ClearAllButtons() + ; } GINPUT gInput; @@ -75,7 +72,6 @@ void ctrlInit(void) void ctrlTerm(void) { - CONTROL_Shutdown(); } int32_t mouseyaxismode = -1; diff --git a/source/blood/src/credits.cpp b/source/blood/src/credits.cpp index 45c2157a2..009f2bf74 100644 --- a/source/blood/src/credits.cpp +++ b/source/blood/src/credits.cpp @@ -26,8 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "compat.h" #include "SmackerDecoder.h" -#include "fx_man.h" -#include "keyboard.h" #include "common_game.h" #include "blood.h" #include "config.h" @@ -37,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "screen.h" #include "sound.h" #include "view.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS @@ -239,13 +238,13 @@ void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav) nScale = divscale16(200, nHeight); if (nWav) - sndStartWavID(nWav, snd_fxvolume); + sndStartWavID(nWav, 255); else { auto nHandleWAV = credKOpen4Load(pzWAV); if (nHandleWAV.isOpen()) { - sndStartWavDisk(pzWAV, snd_fxvolume); + sndStartWavDisk(pzWAV, 255); } } @@ -283,7 +282,7 @@ void credPlaySmk(const char *_pzSMK, const char *_pzWAV, int nWav) Smacker_Close(hSMK); ctrlClearAllInput(); - FX_StopAllSounds(); + soundEngine->StopAllChannels(); videoSetPalette(0, 0, 8+2); tileDelete(kSMKTile); Bfree(pzSMK_); diff --git a/source/blood/src/d_menu.cpp b/source/blood/src/d_menu.cpp index 2b81b6317..579f83293 100644 --- a/source/blood/src/d_menu.cpp +++ b/source/blood/src/d_menu.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "compat.h" -#include "mouse.h" #include "common_game.h" #include "blood.h" #include "config.h" diff --git a/source/blood/src/demo.cpp b/source/blood/src/demo.cpp index 596ac9bc9..52291ce88 100644 --- a/source/blood/src/demo.cpp +++ b/source/blood/src/demo.cpp @@ -27,8 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include "common.h" #include "common_game.h" -#include "keyboard.h" -#include "control.h" #include "osd.h" #include "mmulti.h" @@ -41,7 +39,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "levels.h" #include "messages.h" #include "misc.h" -#include "music.h" #include "network.h" #include "player.h" #include "screen.h" @@ -312,7 +309,6 @@ _DEMOPLAYBACK: while (at1 && !gQuitGame) { handleevents(); - MUSIC_Update(); while (totalclock >= gNetFifoClock && !gQuitGame) { if (!v4) diff --git a/source/blood/src/endgame.cpp b/source/blood/src/endgame.cpp index 4a55bf6d5..c26b7da34 100644 --- a/source/blood/src/endgame.cpp +++ b/source/blood/src/endgame.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "common.h" #include "mmulti.h" -#include "fx_man.h" #include "common_game.h" #include "blood.h" #include "endgame.h" @@ -42,6 +41,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "statistics.h" #include "gamemenu.h" #include "gstrings.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS @@ -119,8 +119,7 @@ void CEndGameMgr::Finish(void) { levelSetupOptions(gGameOptions.nEpisode, gNextLevel); gInitialNetPlayers = numplayers; - FX_StopAllSounds(); - sndKillAllSounds(); + soundEngine->StopAllChannels(); gStartNewGame = 1; gInputMode = (INPUT_MODE)at1; at0 = 0; @@ -220,7 +219,7 @@ void CSecretMgr::Found(int nType) } else at8++; if (gGameOptions.nGameType == 0) { - viewSetMessage(GStrings(FStringf("TXT_SECRET%d", Random(2))), 0, MESSAGE_PRIORITY_SECRET); + viewSetMessage(GStrings(FStringf("TXTB_SECRET%d", Random(2))), 0, MESSAGE_PRIORITY_SECRET); } } diff --git a/source/blood/src/gamemenu.cpp b/source/blood/src/gamemenu.cpp index 4ce789220..31bf46c39 100644 --- a/source/blood/src/gamemenu.cpp +++ b/source/blood/src/gamemenu.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "compat.h" -#include "mouse.h" #include "common_game.h" #include "blood.h" #include "config.h" diff --git a/source/blood/src/menu.cpp b/source/blood/src/menu.cpp index ef66e2a5d..277b287e4 100644 --- a/source/blood/src/menu.cpp +++ b/source/blood/src/menu.cpp @@ -153,7 +153,7 @@ void NetworkHostGame(CGameMenuItemChain *pItem) { UNREFERENCED_PARAMETER(pItem); Mus_Stop(); - FX_StopAllSounds(); + FX_StopAllSounds_(); UpdateDacs(0, true); gNetPlayers = itemNetworkHostPlayerNum.nValue; gNetPort = strtoul(zNetPortBuffer, NULL, 10); @@ -169,7 +169,7 @@ void NetworkJoinGame(CGameMenuItemChain *pItem) { UNREFERENCED_PARAMETER(pItem); Mus_Stop(); - FX_StopAllSounds(); + FX_StopAllSounds_(); UpdateDacs(0, true); strcpy(gNetAddress, zNetAddressBuffer); gNetPort = strtoul(zNetPortBuffer, NULL, 10); diff --git a/source/blood/src/messages.cpp b/source/blood/src/messages.cpp index c93c0f13a..2c2ac7a2f 100644 --- a/source/blood/src/messages.cpp +++ b/source/blood/src/messages.cpp @@ -25,8 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "mmulti.h" #include "compat.h" -#include "keyboard.h" -#include "control.h" #include "gamecontrol.h" #include "common_game.h" #include "blood.h" diff --git a/source/blood/src/osdcmd.cpp b/source/blood/src/osdcmd.cpp index b8d38f114..11d09d5ed 100644 --- a/source/blood/src/osdcmd.cpp +++ b/source/blood/src/osdcmd.cpp @@ -24,12 +24,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "baselayer.h" -#include "keyboard.h" -#include "control.h" #include "osd.h" #include "compat.h" #include "mmulti.h" -#include "sndcards.h" #include "common_game.h" #include "config.h" #include "blood.h" @@ -272,18 +269,6 @@ static int osdcmd_noclip(osdcmdptr_t UNUSED(parm)) return OSDCMD_OK; } -static int osdcmd_restartsound(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - sfxTerm(); - sndTerm(); - - sndInit(); - sfxInit(); - - return OSDCMD_OK; -} - void onvideomodechange(int32_t newmode) { UNREFERENCED_PARAMETER(newmode); @@ -305,7 +290,6 @@ int32_t registerosdcommands(void) OSD_RegisterFunction("give","give : gives requested item", osdcmd_give); OSD_RegisterFunction("god","god: toggles god mode", osdcmd_god); OSD_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip); - OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound); OSD_RegisterFunction("vidmode","vidmode : change the video mode",osdcmd_vidmode); diff --git a/source/blood/src/resource.cpp b/source/blood/src/resource.cpp index 7139f2598..6057ba44a 100644 --- a/source/blood/src/resource.cpp +++ b/source/blood/src/resource.cpp @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include #include "compat.h" -#include "cache1d.h" + #include "common_game.h" #include "misc.h" diff --git a/source/blood/src/seq.cpp b/source/blood/src/seq.cpp index 6c3290e2f..819b58277 100644 --- a/source/blood/src/seq.cpp +++ b/source/blood/src/seq.cpp @@ -39,6 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "actor.h" #include "tile.h" #include "view.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS @@ -327,8 +328,13 @@ void SEQINST::Update(ACTIVE *pActive) }; int sndId = surfSfxMove[surf][Random(2)]; - DICTNODE * hRes = gSoundRes.Lookup(sndId, "SFX"); SFX * pEffect = (SFX*)gSoundRes.Load(hRes); - sfxPlay3DSoundCP(pSprite, sndId, -1, 0, 0, (surfSfxMove[surf][2] != pEffect->relVol) ? pEffect->relVol : surfSfxMove[surf][3]); + auto snd = soundEngine->FindSoundByResID(sndId); + if (snd > 0) + { + auto udata = (int*)soundEngine->GetUserData(snd); + int relVol = udata ? udata[2] : 255; + sfxPlay3DSoundCP(pSprite, sndId, -1, 0, 0, (surfSfxMove[surf][2] != relVol) ? relVol : surfSfxMove[surf][3]); + } } diff --git a/source/blood/src/sfx.cpp b/source/blood/src/sfx.cpp index 538fc16eb..52e8cecdc 100644 --- a/source/blood/src/sfx.cpp +++ b/source/blood/src/sfx.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "compat.h" #include "common_game.h" -#include "fx_man.h" #include "config.h" #include "gameutil.h" @@ -35,338 +34,175 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sfx.h" #include "sound.h" #include "trig.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS -POINT2D earL, earR, earL0, earR0; // Ear position -VECTOR2D earVL, earVR; // Ear velocity ? -int lPhase, rPhase, lVol, rVol, lPitch, rPitch; +class BloodSoundEngine : public SoundEngine +{ + // client specific parts of the sound engine go in this class. + void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan *channel) override; + TArray ReadSound(int lumpnum); -BONKLE Bonkle[256]; -BONKLE *BonkleCache[256]; - -int nBonkles; +public: + BloodSoundEngine() + { + S_Rolloff.RolloffType = ROLLOFF_Doom; + S_Rolloff.MinDistance = 170; // these are the numbers I got when uncrunching the original sound code. + S_Rolloff.MaxDistance = 850; + } +}; void sfxInit(void) { - for (int i = 0; i < 256; i++) - BonkleCache[i] = &Bonkle[i]; - nBonkles = 0; + soundEngine = new BloodSoundEngine; } void sfxTerm() { } -int Vol3d(int angle, int dist) +//========================================================================== +// +// +// +//========================================================================== + +TArray BloodSoundEngine::ReadSound(int lumpnum) { - return dist - mulscale16(dist, 0x2000 - mulscale30(0x2000, Cos(angle))); + auto wlump = fileSystem.OpenFileReader(lumpnum); + return wlump.Read(); } -void Calc3DValues(BONKLE *pBonkle) +void BloodSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan *) { - int dx = pBonkle->at20.x - gMe->pSprite->x; - int dy = pBonkle->at20.y - gMe->pSprite->y; - int dz = pBonkle->at20.z - gMe->pSprite->z; - int angle = getangle(dx, dy); - dx >>= 4; - dy >>= 4; - dz >>= 8; - int distance = ksqrt(dx*dx + dy * dy + dz * dz); - distance = ClipLow((distance >> 2) + (distance >> 3), 64); - int v14, v18; - v14 = v18 = scale(pBonkle->at1c, 80, distance); - int sinVal = Sin(angle); - int cosVal = Cos(angle); - int v8 = dmulscale30r(cosVal, pBonkle->at20.x - pBonkle->at2c.x, sinVal, pBonkle->at20.y - pBonkle->at2c.y); + if (pos != nullptr && type != SOURCE_None) + { + FVector3 camera; + + if (gMe && gMe->pSprite) camera = GetSoundPos(&gMe->pSprite->pos); + else camera = { 0, 0, 0 }; // don't crash if there is no player. - int distanceL = approxDist(pBonkle->at20.x - earL.x, pBonkle->at20.y - earL.y); - lVol = Vol3d(angle - (gMe->pSprite->ang - 85), v18); - int phaseLeft = mulscale16r(distanceL, pBonkle->at3c == 1 ? 4114 : 8228); - lPitch = scale(pBonkle->at18, dmulscale30r(cosVal, earVL.dx, sinVal, earVL.dy) + 5853, v8 + 5853); + if (vel) vel->Zero(); - int distanceR = approxDist(pBonkle->at20.x - earR.x, pBonkle->at20.y - earR.y); - rVol = Vol3d(angle - (gMe->pSprite->ang + 85), v14); - int phaseRight = mulscale16r(distanceR, pBonkle->at3c == 1 ? 4114 : 8228); - rPitch = scale(pBonkle->at18, dmulscale30r(cosVal, earVR.dx, sinVal, earVR.dy) + 5853, v8 + 5853); + if (type == SOURCE_Unattached) + { + pos->X = pt[0]; + pos->Y = pt[1]; + pos->Z = pt[2]; + } + else if (type == SOURCE_Actor) + { + auto actor = (spritetype*)source; + assert(actor != nullptr); + size_t index = actor - sprite; + // Engine expects velocity in units per second, not units per tic. + if (vel) *vel = { xvel[index] * (30 / 65536.f), zvel[index] * (-30 / 65536.f), yvel[index] * (-30 / 65536.f) }; + *pos = GetSoundPos(&actor->pos); + } + else if (type == SOURCE_Ambient) + { + *pos = camera; // just to be safe. Ambient sounds are in the world but unpositioned + } + if ((chanflags & CHANF_LISTENERZ)) + { + pos->Y = camera.Y; + } + } +} - int phaseMin = ClipHigh(phaseLeft, phaseRight); - lPhase = phaseRight - phaseMin; - rPhase = phaseLeft - phaseMin; + +void sfxUpdate3DSounds(void) +{ + SoundListener listener; + + listener.angle = -(float)gMe->pSprite->ang * pi::pi() / 1024; // Build uses a period of 2048. + listener.velocity.Zero(); + listener.position = GetSoundPos(&gMe->pSprite->pos); + listener.underwater = false; + // This should probably use a real environment instead of the pitch hacking in S_PlaySound3D. + // listenactor->waterlevel == 3; + //assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber); + listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment; + listener.valid = true; + + listener.ListenerObject = gMe->pSprite; + soundEngine->SetListener(listener); + soundEngine->UpdateSounds((int)totalclock); +} + +FSoundID getSfx(FSoundID soundId, float &attenuation, int &pitch, int relvol) +{ + auto udata = (int*)soundEngine->GetUserData(soundId); + if (pitch < 0) pitch = udata ? udata[0] : 0x10000; + + if (relvol < 0) relvol = udata && udata[2] ? udata[2] : 80; + if (relvol > 255) relvol = 255; + attenuation = relvol > 0 ? 80.f / relvol : 1.f; + return soundId; } void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector) { if (!SoundEnabled() || soundId < 0) return; - - DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX"); - if (!hRes)return; + auto sid = soundEngine->FindSoundByResID(soundId); + if (sid == 0) return; - SFX *pEffect = (SFX*)gSoundRes.Load(hRes); - hRes = gSoundRes.Lookup(pEffect->rawName, "RAW"); - if (!hRes) return; + vec3_t xyz = { x, y, z }; + auto svec = GetSoundPos(&xyz); + + float attenuation; + int pitch = -1; + sid = getSfx(sid, attenuation, pitch, -1); + + soundEngine->StartSound(SOURCE_Unattached, nullptr, &svec, -1, CHANF_OVERLAP, sid, 0.8f, attenuation, nullptr, pitch / 65536.f); - int v1c, v18; - v1c = v18 = mulscale16(pEffect->pitch, sndGetRate(pEffect->format)); - if (nBonkles >= 256) - return; - BONKLE *pBonkle = BonkleCache[nBonkles++]; - pBonkle->at10 = NULL; - pBonkle->at20.x = x; - pBonkle->at20.y = y; - pBonkle->at20.z = z; - pBonkle->at38 = nSector; - FindSector(x, y, z, &pBonkle->at38); - pBonkle->at2c = pBonkle->at20; - pBonkle->atc = soundId; - pBonkle->at8 = hRes; - pBonkle->at1c = pEffect->relVol; - pBonkle->at18 = v18; - pBonkle->at3c = pEffect->format; - int size = hRes->Size(); - char *pData = (char*)gSoundRes.Lock(hRes); - Calc3DValues(pBonkle); - int priority = 1; - if (priority < lVol) - priority = lVol; - if (priority < rVol) - priority = rVol; - if (snd_doppler) - { - MV_Lock(); - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)&pBonkle->at4); - MV_Unlock(); - } - else - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v1c, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = 0; - } } -void sfxPlay3DSound(spritetype *pSprite, int soundId, int a3, int a4) +enum EPlayFlags { - if (!SoundEnabled()) - return; - if (!pSprite) - return; - if (soundId < 0) - return; - DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX"); - if (!hRes) - return; + FX_GlobalChannel = 1, + FX_SoundMatch = 2, + FX_ChannelMatch = 4, +}; - SFX *pEffect = (SFX*)gSoundRes.Load(hRes); - hRes = gSoundRes.Lookup(pEffect->rawName, "RAW"); - if (!hRes) - return; - int size = hRes->Size(); - if (size <= 0) - return; - int v14; - v14 = mulscale16(pEffect->pitch, sndGetRate(pEffect->format)); - BONKLE *pBonkle = NULL; - if (a3 >= 0) - { - int i; - for (i = 0; i < nBonkles; i++) - { - pBonkle = BonkleCache[i]; - if (pBonkle->at14 == a3 && (pBonkle->at10 == pSprite || (a4 & 1) != 0)) - { - if ((a4 & 4) != 0 && pBonkle->at14 == a3) - return; - if ((a4 & 2) != 0 && pBonkle->atc == soundId) - return; - if (pBonkle->at0 > 0) - FX_StopSound(pBonkle->at0); - if (pBonkle->at4 > 0) - FX_StopSound(pBonkle->at4); - if (pBonkle->at8) - { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; - } - break; - } - } - if (i == nBonkles) - { - if (nBonkles >= 256) - return; - pBonkle = BonkleCache[nBonkles++]; - } - pBonkle->at10 = pSprite; - pBonkle->at14 = a3; - } - else - { - if (nBonkles >= 256) - return; - pBonkle = BonkleCache[nBonkles++]; - pBonkle->at10 = NULL; - } - pBonkle->at20.x = pSprite->x; - pBonkle->at20.y = pSprite->y; - pBonkle->at20.z = pSprite->z; - pBonkle->at38 = pSprite->sectnum; - pBonkle->at2c = pBonkle->at20; - pBonkle->atc = soundId; - pBonkle->at8 = hRes; - pBonkle->at1c = pEffect->relVol; - pBonkle->at18 = v14; - Calc3DValues(pBonkle); - int priority = 1; - if (priority < lVol) - priority = lVol; - if (priority < rVol) - priority = rVol; - int loopStart = pEffect->loopStart; - int loopEnd = ClipLow(size - 1, 0); - if (a3 < 0) - loopStart = -1; - MV_Lock(); - char *pData = (char*)gSoundRes.Lock(hRes); - if (loopStart >= 0) - { - if (snd_doppler) - { - pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = FX_PlayLoopedRaw(pData + rPhase, size - rPhase, pData + loopStart, pData + loopEnd, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)&pBonkle->at4); - } - else - { - pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, v14, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = 0; - } - } - else - { - pData = (char*)gSoundRes.Lock(pBonkle->at8); - if (snd_doppler) - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)&pBonkle->at4); - } - else - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v14, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)&pBonkle->at0); - pBonkle->at4 = 0; - } - } - MV_Unlock(); -} - -// By NoOne: same as previous, but allows to set custom pitch for sound AND volume. Used by SFX gen now. void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitch, int volume) { - if (!SoundEnabled() || !pSprite || soundId < 0) return; - DICTNODE* hRes = gSoundRes.Lookup(soundId, "SFX"); - if (!hRes) return; + if (!SoundEnabled() || soundId < 0 || !pSprite) return; + auto sid = soundEngine->FindSoundByResID(soundId); + if (sid == 0) return; - SFX* pEffect = (SFX*)gSoundRes.Load(hRes); - hRes = gSoundRes.Lookup(pEffect->rawName, "RAW"); - if (!hRes) return; - int size = hRes->Size(); - if (size <= 0) return; - - if (pitch <= 0) pitch = pEffect->pitch; - else pitch -= Random(pEffect->pitchRange); + auto svec = GetSoundPos(&pSprite->pos); + + float attenuation; + sid = getSfx(sid, attenuation, pitch, volume); - int v14; - v14 = mulscale16(pitch, sndGetRate(pEffect->format)); - - BONKLE * pBonkle = NULL; if (a3 >= 0) { - int i; - for (i = 0; i < nBonkles; i++) - { - pBonkle = BonkleCache[i]; - if (pBonkle->at14 == a3 && (pBonkle->at10 == pSprite || (a4 & 1) != 0)) + a3++; // This is to make 0 a valid channel value. + if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int { - if ((a4 & 4) != 0 && pBonkle->at14 == a3) - return; - if ((a4 & 2) != 0 && pBonkle->atc == soundId) - return; - if (pBonkle->at0 > 0) - FX_StopSound(pBonkle->at0); - if (pBonkle->at4 > 0) - FX_StopSound(pBonkle->at4); - if (pBonkle->at8) + if (chan->SourceType != SOURCE_Actor) return false; // other source types are not our business. + if (chan->EntChannel == a3 && (chan->Source == pSprite || (a4 & FX_GlobalChannel) != 0)) { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; + if ((a4 & FX_ChannelMatch) != 0 && chan->EntChannel == a3) + return true; + if ((a4 & FX_SoundMatch) != 0 && chan->OrgID == sid) + return true; + soundEngine->StopChannel(chan); + return -1; } - break; - } - } - if (i == nBonkles) - { - if (nBonkles >= 256) - return; - pBonkle = BonkleCache[nBonkles++]; - } - pBonkle->at10 = pSprite; - pBonkle->at14 = a3; + return false; + })) return; + } - else - { - if (nBonkles >= 256) - return; - pBonkle = BonkleCache[nBonkles++]; - pBonkle->at10 = NULL; - } - pBonkle->at20.x = pSprite->x; - pBonkle->at20.y = pSprite->y; - pBonkle->at20.z = pSprite->z; - pBonkle->at38 = pSprite->sectnum; - pBonkle->at2c = pBonkle->at20; - pBonkle->atc = soundId; - pBonkle->at8 = hRes; - pBonkle->at1c = ((volume == 0) ? pEffect->relVol : ((volume == -1) ? 0 : ((volume > 255) ? 255 : volume))); - pBonkle->at18 = v14; - Calc3DValues(pBonkle); - int priority = 1; - if (priority < lVol) - priority = lVol; - if (priority < rVol) - priority = rVol; - int loopStart = pEffect->loopStart; - int loopEnd = ClipLow(size - 1, 0); - if (a3 < 0) - loopStart = -1; - MV_Lock(); - char* pData = (char*)gSoundRes.Lock(hRes); - if (loopStart >= 0) - { - if (snd_doppler) - { - pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)& pBonkle->at0); - pBonkle->at4 = FX_PlayLoopedRaw(pData + rPhase, size - rPhase, pData + loopStart, pData + loopEnd, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)& pBonkle->at4); - } - else - { - pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, v14, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)& pBonkle->at0); - pBonkle->at4 = 0; - } - } - else - { - pData = (char*)gSoundRes.Lock(pBonkle->at8); - if (snd_doppler) - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, 1.f, (intptr_t)& pBonkle->at0); - pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, 1.f, (intptr_t)& pBonkle->at4); - } - else - { - pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v14, 0, lVol, lVol, rVol, priority, 1.f, (intptr_t)& pBonkle->at0); - pBonkle->at4 = 0; - } - } - MV_Unlock(); + + soundEngine->StartSound(SOURCE_Actor, pSprite, &svec, a3, a3 == -1? CHANF_OVERLAP : CHANF_NONE , sid, 0.8f, attenuation, nullptr, pitch / 65536.f); +} + +void sfxPlay3DSound(spritetype* pSprite, int soundId, int a3, int a4) +{ + sfxPlay3DSoundCP(pSprite, soundId, a3, a4, -1, -1); } @@ -374,115 +210,27 @@ void sfxKill3DSound(spritetype *pSprite, int a2, int a3) { if (!pSprite) return; - for (int i = nBonkles - 1; i >= 0; i--) - { - BONKLE *pBonkle = BonkleCache[i]; - if (pBonkle->at10 == pSprite && (a2 < 0 || a2 == pBonkle->at14) && (a3 < 0 || a3 == pBonkle->atc)) + + if (a2 >= 0) a2++; + soundEngine->EnumerateChannels([=](FSoundChan* channel) { - if (pBonkle->at0 > 0) + if (channel->SourceType == SOURCE_Actor && channel->Source == pSprite && (a2 < 0 || a2 == channel->EntChannel) && (a3 < 0 || a3 == channel->OrgID)) { - FX_EndLooping(pBonkle->at0); - FX_StopSound(pBonkle->at0); + soundEngine->StopChannel(channel); } - if (pBonkle->at4 > 0) - { - FX_EndLooping(pBonkle->at4); - FX_StopSound(pBonkle->at4); - } - if (pBonkle->at8) - { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; - } - BonkleCache[i] = BonkleCache[--nBonkles]; - BonkleCache[nBonkles] = pBonkle; - break; - } - } + return false; + }); } void sfxKillAllSounds(void) { - for (int i = nBonkles - 1; i >= 0; i--) + soundEngine->EnumerateChannels([](FSoundChan* channel) { - BONKLE *pBonkle = BonkleCache[i]; - if (pBonkle->at0 > 0) - { - FX_EndLooping(pBonkle->at0); - FX_StopSound(pBonkle->at0); - } - if (pBonkle->at4 > 0) - { - FX_EndLooping(pBonkle->at4); - FX_StopSound(pBonkle->at4); - } - if (pBonkle->at8) - { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; - } - BonkleCache[i] = BonkleCache[--nBonkles]; - BonkleCache[nBonkles] = pBonkle; - } + if (channel->SourceType == SOURCE_Actor || channel->SourceType == SOURCE_Unattached) soundEngine->StopChannel(channel); + return false; + }); } -void sfxUpdate3DSounds(void) -{ - int dx = mulscale30(Cos(gMe->pSprite->ang + 512), 43); - earL0 = earL; - int dy = mulscale30(Sin(gMe->pSprite->ang + 512), 43); - earR0 = earR; - earL.x = gMe->pSprite->x - dx; - earL.y = gMe->pSprite->y - dy; - earR.x = gMe->pSprite->x + dx; - earR.y = gMe->pSprite->y + dy; - earVL.dx = earL.x - earL0.x; - earVL.dy = earL.y - earL0.y; - earVR.dx = earR.x - earR0.x; - earVR.dy = earR.y - earR0.y; - for (int i = nBonkles - 1; i >= 0; i--) - { - BONKLE *pBonkle = BonkleCache[i]; - if (pBonkle->at0 > 0 || pBonkle->at4 > 0) - { - if (!pBonkle->at8) - continue; - if (pBonkle->at10) - { - pBonkle->at2c = pBonkle->at20; - pBonkle->at20.x = pBonkle->at10->x; - pBonkle->at20.y = pBonkle->at10->y; - pBonkle->at20.z = pBonkle->at10->z; - pBonkle->at38 = pBonkle->at10->sectnum; - } - Calc3DValues(pBonkle); - MV_Lock(); - if (pBonkle->at0 > 0) - { - if (pBonkle->at4 > 0) - { - FX_SetPan(pBonkle->at0, lVol, lVol, 0); - FX_SetFrequency(pBonkle->at0, lPitch); - } - else - FX_SetPan(pBonkle->at0, lVol, lVol, rVol); - } - if (pBonkle->at4 > 0) - { - FX_SetPan(pBonkle->at4, rVol, 0, rVol); - FX_SetFrequency(pBonkle->at4, rPitch); - } - MV_Unlock(); - } - else - { - gSoundRes.Unlock(pBonkle->at8); - pBonkle->at8 = NULL; - BonkleCache[i] = BonkleCache[--nBonkles]; - BonkleCache[nBonkles] = pBonkle; - } - } -} void sfxSetReverb(bool toggle) { diff --git a/source/blood/src/sfx.h b/source/blood/src/sfx.h index 4bc8f1abd..4126012f2 100644 --- a/source/blood/src/sfx.h +++ b/source/blood/src/sfx.h @@ -25,30 +25,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS +#if 0 struct BONKLE { - int at0; - int at4; - DICTNODE* at8; - int atc; - spritetype* at10; - int at14; - int at18; - int at1c; - POINT3D at20; - POINT3D at2c; - //int at20; - //int at24; - //int at28; - //int at2c; - //int at30; - //int at34; - int at38; - int at3c; + int left; + int right; + DICTNODE* data; + int soundId; + spritetype* origin; + int channel; + int pitch; + int relVol; + POINT3D originPt; + POINT3D oldOriginPt; }; extern BONKLE Bonkle[256]; extern BONKLE* BonkleCache[256]; +#endif void sfxInit(void); void sfxTerm(void); diff --git a/source/blood/src/sound.cpp b/source/blood/src/sound.cpp index c844d5e3a..22583644c 100644 --- a/source/blood/src/sound.cpp +++ b/source/blood/src/sound.cpp @@ -24,22 +24,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "compat.h" -#include "music.h" -#include "fx_man.h" #include "common_game.h" #include "config.h" #include "levels.h" #include "resource.h" #include "sound.h" #include "renderlayer.h" -#include "al_midi.h" #include "openaudio.h" #include "z_music.h" +#include "sfx.h" +#include "sound/s_soundinternal.h" BEGIN_BLD_NS -Resource& gSoundRes = fileSystem; - int soundRates[13] = { 11025, 11025, @@ -57,6 +54,72 @@ int soundRates[13] = { }; #define kChannelMax 32 + +//========================================================================== +// +// S_AddBloodSFX +// +// Registers a new sound with the name ".sfx" +// Actual sound data is searched for in the ns_bloodraw namespace. +// +//========================================================================== + +static void S_AddBloodSFX(int lumpnum) +{ + auto sfxlump = fileSystem.ReadFile(lumpnum); + const SFX* sfx = (SFX*)sfxlump.GetMem(); + FStringf rawname("%s.raw", sfx->rawName); + auto rawlump = fileSystem.FindFile(rawname); + int sfxnum; + + if (rawlump != -1) + { + auto& S_sfx = soundEngine->GetSounds(); + sfxnum = soundEngine->AddSoundLump(sfx->rawName, rawlump, 0, fileSystem.GetResourceId(lumpnum), 6); + if (sfx->format < 5 || sfx->format > 12) + { // [0..4] + invalid formats + S_sfx[sfxnum].RawRate = 11025; + } + else if (sfx->format < 9) + { // [5..8] + S_sfx[sfxnum].RawRate = 22050; + } + else + { // [9..12] + S_sfx[sfxnum].RawRate = 44100; + } + S_sfx[sfxnum].bLoadRAW = true; + S_sfx[sfxnum].LoopStart = LittleLong(sfx->loopStart); + //S_sfx[sfxnum].Volume = sfx->relVol / 255.f; This cannot be done because this volume setting is optional. + S_sfx[sfxnum].UserData.Resize(8); + int* udata = (int*)S_sfx[sfxnum].UserData.Data(); + udata[0] = sfx->pitch; + udata[1] = sfx->pitchRange; + udata[2] = sfx->relVol; } +} + +void sndInit(void) +{ + sfxInit(); + for (int i = fileSystem.GetNumEntries() - 1; i >= 0; i--) + { + auto type = fileSystem.GetResourceType(i); + if (type == NAME_SFX) + { + if (soundEngine->FindSoundByResID(fileSystem.GetResourceId(i)) == 0) + S_AddBloodSFX(i); + } + else if (type == NAME_WAV || type == NAME_OGG || type == NAME_FLAC || type == NAME_VOC) + { + soundEngine->AddSoundLump(fileSystem.GetFileName(i), i, 0, fileSystem.GetResourceId(i)| 0x40000000, 6); // mark the resource ID as special. + } + } + soundEngine->HashSounds(); +} + + + + int sndGetRate(int format) { if (format < 13) @@ -64,22 +127,6 @@ int sndGetRate(int format) return 11025; } -SAMPLE2D Channel[kChannelMax]; - -SAMPLE2D * FindChannel(void) -{ - for (int i = kChannelMax - 1; i >= 0; i--) - if (Channel[i].at5 == 0) return &Channel[i]; - consoleSysMsg("No free channel available for sample"); - //ThrowError("No free channel available for sample"); - return NULL; -} - -void sndSetFXVolume(int nVolume) -{ - snd_fxvolume = nVolume; - FX_SetVolume(nVolume); -} void SoundCallback(intptr_t val) @@ -88,8 +135,6 @@ void SoundCallback(intptr_t val) pChannel->at0 = 0; } -void sndKillSound(SAMPLE2D *pChannel); - void sndStartSample(const char *pzSound, int nVolume, int nChannel) { if (!SoundEnabled()) @@ -97,19 +142,11 @@ void sndStartSample(const char *pzSound, int nVolume, int nChannel) if (!strlen(pzSound)) return; dassert(nChannel >= -1 && nChannel < kChannelMax); - SAMPLE2D *pChannel; - if (nChannel == -1) - pChannel = FindChannel(); - else - pChannel = &Channel[nChannel]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - pChannel->at5 = gSoundRes.Lookup(pzSound, "RAW"); - if (!pChannel->at5) - return; - int nSize = pChannel->at5->Size(); - char *pData = (char*)gSoundRes.Lock(pChannel->at5); - pChannel->at0 = FX_PlayRaw(pData, nSize, sndGetRate(1), 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); + auto snd = soundEngine->FindSound(pzSound); + if (snd > 0) + { + soundEngine->StartSound(SOURCE_None, nullptr, nullptr, nChannel + 1, 0, snd, nVolume / 255.f, ATTN_NONE); + } } void sndStartSample(unsigned int nSound, int nVolume, int nChannel, bool bLoop) @@ -117,193 +154,35 @@ void sndStartSample(unsigned int nSound, int nVolume, int nChannel, bool bLoop) if (!SoundEnabled()) return; dassert(nChannel >= -1 && nChannel < kChannelMax); - DICTNODE *hSfx = gSoundRes.Lookup(nSound, "SFX"); - if (!hSfx) - return; - SFX *pEffect = (SFX*)gSoundRes.Lock(hSfx); - dassert(pEffect != NULL); - SAMPLE2D *pChannel; - if (nChannel == -1) - pChannel = FindChannel(); - else - pChannel = &Channel[nChannel]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - pChannel->at5 = gSoundRes.Lookup(pEffect->rawName, "RAW"); - if (!pChannel->at5) - return; - if (nVolume < 0) - nVolume = pEffect->relVol; - int nSize = pChannel->at5->Size(); - int nLoopEnd = nSize - 1; - if (nLoopEnd < 0) - nLoopEnd = 0; - if (nSize <= 0) - return; - char *pData = (char*)gSoundRes.Lock(pChannel->at5); - if (nChannel < 0) - bLoop = false; - if (bLoop) + if (nChannel >= 7) nChannel = -1; + auto snd = soundEngine->FindSoundByResID(nSound); + if (snd > 0) { - pChannel->at0 = FX_PlayLoopedRaw(pData, nSize, pData + pEffect->loopStart, pData + nLoopEnd, sndGetRate(pEffect->format), - 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); - pChannel->at4 |= 1; - } - else - { - pChannel->at0 = FX_PlayRaw(pData, nSize, sndGetRate(pEffect->format), 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); - pChannel->at4 &= ~1; + if (nVolume < 0) + { + auto udata = (int*)soundEngine->GetUserData(snd); + if (udata) nVolume = udata[2]; + else nVolume = 255; + } + soundEngine->StartSound(SOURCE_None, nullptr, nullptr, (nChannel + 1), (bLoop? CHANF_LOOP : EChanFlags::FromInt(0)), snd, nVolume / 255.f, ATTN_NONE); } } void sndStartWavID(unsigned int nSound, int nVolume, int nChannel) { - if (!SoundEnabled()) - return; - dassert(nChannel >= -1 && nChannel < kChannelMax); - SAMPLE2D *pChannel; - if (nChannel == -1) - pChannel = FindChannel(); - else - pChannel = &Channel[nChannel]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - pChannel->at5 = gSoundRes.Lookup(nSound, "WAV"); - if (!pChannel->at5) - return; - char *pData = (char*)gSoundRes.Lock(pChannel->at5); - pChannel->at0 = FX_Play(pData, pChannel->at5->Size(), 0, -1, 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); -} - -void sndKillSound(SAMPLE2D *pChannel) -{ - if (pChannel->at4 & 1) - { - FX_EndLooping(pChannel->at0); - pChannel->at4 &= ~1; - } - FX_StopSound(pChannel->at0); + return sndStartSample(nSound | 0x40000000, nVolume, nChannel); } void sndStartWavDisk(const char *pzFile, int nVolume, int nChannel) { - dassert(nChannel >= -1 && nChannel < kChannelMax); - SAMPLE2D *pChannel; - if (nChannel == -1) - pChannel = FindChannel(); - else - pChannel = &Channel[nChannel]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - auto hFile = fileSystem.OpenFileReader(pzFile, 0); - if (!hFile.isOpen()) - return; - int nLength = hFile.GetLength(); - char* pData = nullptr; - cacheAllocateBlock((intptr_t*)pData, nLength, nullptr); // use this obsolete call to indicate that some work is needed here! - if (!pData) - { - return; - } - hFile.Read(pData, nLength); - pChannel->at5 = (DICTNODE*)pData; - pChannel->at4 |= 2; - pChannel->at0 = FX_Play(pData, nLength, 0, -1, 0, nVolume, nVolume, nVolume, nVolume, 1.f, (intptr_t)&pChannel->at0); + return sndStartSample(pzFile, nVolume, nChannel); } void sndKillAllSounds(void) { - for (int i = 0; i < kChannelMax; i++) - { - SAMPLE2D *pChannel = &Channel[i]; - if (pChannel->at0 > 0) - sndKillSound(pChannel); - if (pChannel->at5) - { - if (pChannel->at4 & 2) - { - pChannel->at4 &= ~2; - } - else // This 'else' needs to be removed once the file system is up (when cacheAllocateBlock gets replaced.) - { - gSoundRes.Unlock(pChannel->at5); - } - pChannel->at5 = 0; - } - } -} - -void sndProcess(void) -{ - for (int i = 0; i < kChannelMax; i++) - { - if (Channel[i].at0 <= 0 && Channel[i].at5) - { - if (Channel[i].at4 & 2) - { - Channel[i].at4 &= ~2; - } - else // This 'else' needs to be removed once the file system is up (when cacheAllocateBlock gets replaced.) - { - gSoundRes.Unlock(Channel[i].at5); - } - Channel[i].at5 = 0; - } - } -} - -void InitSoundDevice(void) -{ -#ifdef MIXERTYPEWIN - void *initdata = (void *)win_gethwnd(); // used for DirectSound -#else - void *initdata = NULL; -#endif - int nStatus; - nStatus = FX_Init(snd_numvoices, snd_numchannels, snd_mixrate, initdata); - if (nStatus != 0) - { - initprintf("InitSoundDevice: %s\n", FX_ErrorString(nStatus)); - return; - } - snd_reversestereo.Callback(); - snd_fxvolume.Callback(); - FX_SetCallBack(SoundCallback); -} - -void DeinitSoundDevice(void) -{ - int nStatus = FX_Shutdown(); - if (nStatus != 0) - ThrowError(FX_ErrorString(nStatus)); + soundEngine->StopSound(CHAN_AUTO); } -bool sndActive = false; - -void sndTerm(void) -{ - if (!sndActive) - return; - sndActive = false; - Mus_Stop(); - DeinitSoundDevice(); - //DeinitMusicDevice(); -} -extern char *pUserSoundRFF; -void sndInit(void) -{ - memset(Channel, 0, sizeof(Channel)); -#if 0 - pSongPtr = NULL; - nSongSize = 0; - bWaveMusic = false; - nWaveMusicHandle = -1; -#endif - InitSoundDevice(); - //InitMusicDevice(); - //atexit(sndTerm); - sndActive = true; -} END_BLD_NS diff --git a/source/blood/src/sound.h b/source/blood/src/sound.h index ccc31501e..c5aa22d1a 100644 --- a/source/blood/src/sound.h +++ b/source/blood/src/sound.h @@ -45,7 +45,6 @@ struct SFX }; int sndGetRate(int format); -void sndSetFXVolume(int nVolume); void sndStartSample(const char *pzSound, int nVolume, int nChannel = -1); void sndStartSample(unsigned int nSound, int nVolume, int nChannel = -1, bool bLoop = false); void sndStartWavID(unsigned int nSound, int nVolume, int nChannel = -1); @@ -55,6 +54,4 @@ void sndProcess(void); void sndTerm(void); void sndInit(void); -extern Resource &gSoundRes; - END_BLD_NS diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h index f8bf9d644..bc7b25ad8 100644 --- a/source/build/include/baselayer.h +++ b/source/build/include/baselayer.h @@ -149,9 +149,6 @@ void mouseGrabInput(bool grab); void mouseLockToWindow(bool a); void mouseMoveToCenter(void); -void joyReadButtons(int32_t *pResult); -void joySetDeadZone(int32_t axis, uint16_t dead, uint16_t satur); -void joyGetDeadZone(int32_t axis, uint16_t *dead, uint16_t *satur); extern int32_t inputchecked; void getScreen(uint8_t* imgBuf); diff --git a/source/build/include/build.h b/source/build/include/build.h index 28f1e5db1..9439f5e21 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -27,7 +27,7 @@ static_assert('\xff' == 255, "Char must be unsigned!"); #include "palette.h" #include "pragmas.h" -#include "cache1d.h" + #include "textures.h" #include "c_cvars.h" @@ -866,6 +866,7 @@ static FORCE_INLINE void rotatesprite_win(int32_t sx, int32_t sy, int32_t z, int void getzrange(const vec3_t *pos, int16_t sectnum, int32_t *ceilz, int32_t *ceilhit, int32_t *florz, int32_t *florhit, int32_t walldist, uint32_t cliptype) ATTRIBUTE((nonnull(1,3,4,5,6))); +extern vec2_t hitscangoal; int32_t hitscan(const vec3_t *sv, int16_t sectnum, int32_t vx, int32_t vy, int32_t vz, hitdata_t *hitinfo, uint32_t cliptype) ATTRIBUTE((nonnull(1,6))); void neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange, @@ -1115,6 +1116,7 @@ int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, f extern GrowArray g_clipMapFiles; #endif +EXTERN int32_t nextvoxid; EXTERN intptr_t voxoff[MAXVOXELS][MAXVOXMIPS]; // used in KenBuild EXTERN int8_t voxreserve[(MAXVOXELS+7)>>3]; EXTERN int8_t voxrotate[(MAXVOXELS+7)>>3]; diff --git a/source/build/include/cache1d.h b/source/build/include/cache1d.h deleted file mode 100644 index 4e6983879..000000000 --- a/source/build/include/cache1d.h +++ /dev/null @@ -1,15 +0,0 @@ -// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman -// Ken Silverman's official web site: "http://www.advsys.net/ken" -// See the included license file "BUILDLIC.TXT" for license info. -// -// This file has been modified from Ken Silverman's original release -// by Jonathon Fowler (jf@jonof.id.au) -// by the EDuke32 team (development@voidpoint.com) - -#ifndef cache1d_h_ -#define cache1d_h_ - -void cacheAllocateBlock(intptr_t *newhandle, int32_t newbytes, uint8_t *newlockptr); - -#endif // cache1d_h_ - diff --git a/source/build/include/common.h b/source/build/include/common.h index c91407641..2a787f26e 100644 --- a/source/build/include/common.h +++ b/source/build/include/common.h @@ -7,7 +7,7 @@ #ifndef EDUKE32_COMMON_H_ #define EDUKE32_COMMON_H_ -#include "cache1d.h" + #include "compat.h" #include "pragmas.h" // klabs #include "scriptfile.h" @@ -66,8 +66,6 @@ static inline void realloc_copy(char **fn, const char *buf) int32_t getatoken(scriptfile *sf, const tokenlist *tl, int32_t ntokens); -int32_t G_CheckCmdSwitch(int32_t argc, char const * const * argv, const char *str); - int32_t maybe_append_ext(char *wbuf, int32_t wbufsiz, const char *fn, const char *ext); // Approximations to 2D and 3D Euclidean distances. Initial EDuke32 SVN import says @@ -78,11 +76,8 @@ static inline int32_t sepldist(const int32_t dx, const int32_t dy) { vec2_t d = { klabs(dx), klabs(dy) }; - if (playing_rr) - { - if (!d.y) return d.x; - if (!d.x) return d.y; - } + if (!d.y) return d.x; + if (!d.x) return d.y; if (d.x < d.y) swaplong(&d.x, &d.y); diff --git a/source/build/include/compat.h b/source/build/include/compat.h index e0da70d05..1a56dd50d 100644 --- a/source/build/include/compat.h +++ b/source/build/include/compat.h @@ -750,8 +750,6 @@ typedef struct MAY_ALIAS { int16_t x, y; } vec2_16_t; -using vec2_16_t = vec2_16_t; - typedef struct { uint32_t x, y; } vec2u_t; @@ -1300,6 +1298,16 @@ static inline void maybe_grow_buffer(char ** const buffer, int32_t * const buffe #include "fix16.h" #include "libdivide.h" #include "clockticks.hpp" +#include "vectors.h" + +inline FVector3 GetSoundPos(const vec3_t *pos) +{ + // converts a Build coordinate to a sound system coordinate + const float xmul = 1 / 16.f; + const float ymul = -1 / 16.f; + const float zmul = -1 / 256.f; + return { pos->x* xmul, pos->z* zmul, pos->y* ymul }; +} /* End dependence on compat.o object. */ diff --git a/source/build/include/pragmas.h b/source/build/include/pragmas.h index 527cb03eb..922917289 100644 --- a/source/build/include/pragmas.h +++ b/source/build/include/pragmas.h @@ -189,6 +189,9 @@ void qinterpolatedown16short(intptr_t bufptr, int32_t num, int32_t val, int32_t #ifndef pragmas_have_clearbuf void clearbuf(void *d, int32_t c, int32_t a); #endif +#ifndef pragmas_have_copybuf +void copybuf(const void *s, void *d, int32_t c); +#endif #ifndef pragmas_have_swaps void swapbuf4(void *a, void *b, int32_t c); #endif @@ -196,6 +199,9 @@ void swapbuf4(void *a, void *b, int32_t c); #ifndef pragmas_have_clearbufbyte void clearbufbyte(void *D, int32_t c, int32_t a); #endif +#ifndef pragmas_have_copybufbyte +void copybufbyte(const void *S, void *D, int32_t c); +#endif #ifndef pragmas_have_copybufreverse void copybufreverse(const void *S, void *D, int32_t c); #endif diff --git a/source/build/src/animvpx.cpp b/source/build/src/animvpx.cpp index 411d118f5..46a2e9343 100644 --- a/source/build/src/animvpx.cpp +++ b/source/build/src/animvpx.cpp @@ -7,7 +7,7 @@ #include "compat.h" #include "baselayer.h" #include "build.h" -#include "cache1d.h" + #include "matrix.h" #include "../../glbackend/glbackend.h" diff --git a/source/build/src/baselayer.cpp b/source/build/src/baselayer.cpp index f8253425c..b184438db 100644 --- a/source/build/src/baselayer.cpp +++ b/source/build/src/baselayer.cpp @@ -7,7 +7,7 @@ #include "a.h" #include "polymost.h" -#include "cache1d.h" + #include "inputstate.h" #include "d_event.h" #include "../../glbackend/glbackend.h" @@ -35,8 +35,6 @@ bool g_mouseLockedToWindow = 1; controllerinput_t joystick; -void joySetCallback(void (*callback)(int32_t, int32_t)) { joystick.pCallback = callback; } -void joyReadButtons(int32_t *pResult) { *pResult = appactive ? joystick.bits : 0; } // Calculate ylookup[] and call setvlinebpl() void calc_ylookup(int32_t bpl, int32_t lastyidx) diff --git a/source/build/src/cache1d.cpp b/source/build/src/cache1d.cpp deleted file mode 100644 index ce903189b..000000000 --- a/source/build/src/cache1d.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman -// Ken Silverman's official web site: "http://www.advsys.net/ken" -// See the included license file "BUILDLIC.TXT" for license info. -// -// This file has been modified from Ken Silverman's original release -// by Jonathon Fowler (jf@jonof.id.au) -// by the EDuke32 team (development@voidpoint.com) - -#include -#include "tarray.h" -#include "cache1d.h" - -// Only the sound code still uses this - but it never frees the data. -// So we may just toss out the cache and do regular allocations. -// The TArray is merely for taking down the data before shutdown. -static TArray> pseudocache; - -void cacheAllocateBlock(intptr_t *newhandle, int32_t newbytes, uint8_t *) -{ - pseudocache.Reserve(1); - auto& buffer = pseudocache.Last(); - buffer.Resize(newbytes); - *newhandle = reinterpret_cast(buffer.Data()); -} - diff --git a/source/build/src/common.cpp b/source/build/src/common.cpp index 5531f8d81..f7698b2cc 100644 --- a/source/build/src/common.cpp +++ b/source/build/src/common.cpp @@ -2,7 +2,7 @@ #include "compat.h" #include "build.h" #include "scriptfile.h" -#include "cache1d.h" + #include "baselayer.h" #include "common.h" @@ -57,20 +57,6 @@ int32_t getatoken(scriptfile *sf, const tokenlist *tl, int32_t ntokens) ////////// -int32_t G_CheckCmdSwitch(int32_t argc, char const * const * argv, const char *str) -{ - int32_t i; - for (i=0; itextptr < ifmatchend) + { + int32_t token = getatoken(script,ifmatchtokens,ARRAY_SIZE(ifmatchtokens)); + switch (token) + { + case T_CRC32: + scriptfile_getsymbol(script, &tile_crc32); + have_crc32 = 1; + break; + case T_SIZE: + scriptfile_getsymbol(script, &tile_size.x); + scriptfile_getsymbol(script, &tile_size.y); + have_size = 1; + break; + default: + break; + } + } + break; + } case T_TEXHITSCAN: flags |= PICANM_TEXHITSCAN_BIT; break; @@ -722,12 +756,22 @@ static int32_t defsparser(scriptfile *script) break; } - if (have_ifcrc) + if (have_crc32) { - int32_t origcrc = tileCRC(tile); - if (origcrc != tilecrc) + int32_t const orig_crc32 = tileCRC(tile); + if (orig_crc32 != tile_crc32) { - //initprintf("CRC of tile %d doesn't match! CRC: %d, Expected: %d\n", tile, origcrc, tilecrc); + // initprintf("CRC32 of tile %d doesn't match! CRC32: %d, Expected: %d\n", tile, orig_crc32, tile_crc32); + break; + } + } + + if (have_size) + { + vec2_16_t const orig_size = tilesiz[tile]; + if (orig_size.x != tile_size.x && orig_size.y != tile_size.y) + { + // initprintf("Size of tile %d doesn't match! Size: (%d, %d), Expected: (%d, %d)\n", tile, orig_size.x, orig_size.y, tile_size.x, tile_size.y); break; } } @@ -3409,7 +3453,7 @@ int32_t loaddefinitionsfile(const char *fn) defsparser(script); } - for (auto& m : *userConfig.AddDefs) + if (userConfig.AddDefs) for (auto& m : *userConfig.AddDefs) defsparser_include(m, NULL, NULL); g_logFlushWindow = f; diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 333f804fe..28387bc8a 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -11,7 +11,7 @@ #include "a.h" #include "baselayer.h" #include "build.h" -#include "cache1d.h" + #include "colmatch.h" #include "common.h" #include "compat.h" @@ -4478,7 +4478,7 @@ static void classicDrawBunches(int32_t bunch) smostwall[smostwallcnt] = z; smostwalltype[smostwallcnt] = 1; //1 for umost smostwallcnt++; - memcpy(&umost[x1],&smost[smostcnt],i*sizeof(smost[0])); + copybufbyte(&umost[x1],&smost[smostcnt],i*sizeof(smost[0])); smostcnt += i; } } @@ -4564,7 +4564,7 @@ static void classicDrawBunches(int32_t bunch) smostwall[smostwallcnt] = z; smostwalltype[smostwallcnt] = 2; //2 for dmost smostwallcnt++; - memcpy(&dmost[x1],&smost[smostcnt],i*sizeof(smost[0])); + copybufbyte(&dmost[x1],&smost[smostcnt],i*sizeof(smost[0])); smostcnt += i; } } @@ -5033,6 +5033,16 @@ static void classicDrawVoxel(int32_t dasprx, int32_t daspry, int32_t dasprz, int } } +#if 0 + for (x=0; x=0 && daumost[x]=0 && dadmost[x]>1; horizlookup2[horizycent-1] = divscale32(131072,j); for (i=0; i < horizycent-1; i++) @@ -10146,6 +10157,9 @@ void videoNextPage(void) int32_t qloadkvx(int32_t voxindex, const char *filename) { + if ((unsigned)voxindex >= MAXVOXELS) + return -1; + auto fil = fileSystem.OpenFileReader(filename, 0); if (!fil.isOpen()) return -1; @@ -11637,8 +11651,8 @@ void renderSetTarget(int16_t tilenume, int32_t xsiz, int32_t ysiz) rendmode = REND_CLASSIC; #endif - memcpy(&startumost[windowxy1.x],&bakumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakumost[0])); - memcpy(&startdmost[windowxy1.x],&bakdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakdmost[0])); + copybufbyte(&startumost[windowxy1.x],&bakumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakumost[0])); + copybufbyte(&startdmost[windowxy1.x],&bakdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(bakdmost[0])); setviewcnt++; offscreenrendering = 1; @@ -11672,8 +11686,8 @@ void renderRestoreTarget(void) ydim = bakysiz[setviewcnt]; videoSetViewableArea(bakwindowxy1[setviewcnt].x,bakwindowxy1[setviewcnt].y, bakwindowxy2[setviewcnt].x,bakwindowxy2[setviewcnt].y); - memcpy(&bakumost[windowxy1.x],&startumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startumost[0])); - memcpy(&bakdmost[windowxy1.x],&startdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startdmost[0])); + copybufbyte(&bakumost[windowxy1.x],&startumost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startumost[0])); + copybufbyte(&bakdmost[windowxy1.x],&startdmost[windowxy1.x],(windowxy2.x-windowxy1.x+1)*sizeof(startdmost[0])); frameplace = bakframeplace[setviewcnt]; calc_ylookup((setviewcnt == 0) ? bytesperline : bakxsiz[setviewcnt], diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp index a7d1191e0..db9fc050e 100644 --- a/source/build/src/mdsprite.cpp +++ b/source/build/src/mdsprite.cpp @@ -10,7 +10,7 @@ #include "hightile.h" #include "polymost.h" #include "mdsprite.h" -#include "cache1d.h" + #include "common.h" #include "palette.h" #include "textures.h" diff --git a/source/build/src/palette.cpp b/source/build/src/palette.cpp index 0a38ad35b..569ffef40 100644 --- a/source/build/src/palette.cpp +++ b/source/build/src/palette.cpp @@ -11,7 +11,7 @@ #include "engine_priv.h" #include "baselayer.h" #include "colmatch.h" -#include "cache1d.h" + #include "palette.h" #include "a.h" #include "superfasthash.h" diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 1a70867e3..632d06c7f 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -3995,17 +3995,21 @@ void polymost_drawsprite(int32_t snum) break; // else, render as flat sprite } - if (r_voxels && (tspr->cstat & 48) != 48 && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) + if (r_voxels) { - if (polymost_voxdraw(voxmodels[tiletovox[tspr->picnum]], tspr)) return; - break; // else, render as flat sprite + if ((tspr->cstat & 48) != 48 && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]]) + { + if (polymost_voxdraw(voxmodels[tiletovox[tspr->picnum]], tspr)) return; + break; // else, render as flat sprite + } + + if ((tspr->cstat & 48) == 48 && voxmodels[tspr->picnum]) + { + polymost_voxdraw(voxmodels[tspr->picnum], tspr); + return; + } } - if ((tspr->cstat & 48) == 48 && voxmodels[tspr->picnum]) - { - polymost_voxdraw(voxmodels[tspr->picnum], tspr); - return; - } break; } diff --git a/source/build/src/pragmas.cpp b/source/build/src/pragmas.cpp index 1d81f48e6..219849540 100644 --- a/source/build/src/pragmas.cpp +++ b/source/build/src/pragmas.cpp @@ -71,6 +71,17 @@ void clearbuf(void *d, int32_t c, int32_t a) } #endif +#ifndef pragmas_have_copybuf +void copybuf(const void *s, void *d, int32_t c) +{ + auto p = (const int32_t *) s; + auto q = (int32_t *) d; + + while (c--) + *q++ = *p++; +} +#endif + #ifndef pragmas_have_swaps void swapbuf4(void *a, void *b, int32_t c) { @@ -102,6 +113,16 @@ void clearbufbyte(void *D, int32_t c, int32_t a) } #endif +#ifndef pragmas_have_copybufbyte +void copybufbyte(const void *s, void *d, int32_t c) +{ + auto src = (const char *)s; + auto dst = (char *)d; + + while (c--) + *dst++ = *src++; +} +#endif // copybufreverse() is a special case: use the assembly version for GCC on x86 diff --git a/source/build/src/screenshot.cpp b/source/build/src/screenshot.cpp deleted file mode 100644 index 21f8649d5..000000000 --- a/source/build/src/screenshot.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include "compat.h" -#include "build.h" -#include "baselayer.h" -#include "version.h" -#include "m_png.h" -#include "i_specialpaths.h" -#include "m_argv.h" -#include "cmdlib.h" -#include "gamecontrol.h" -#include "printf.h" -#include "c_dispatch.h" - -#include "../../glbackend/glbackend.h" - -EXTERN_CVAR(Float, png_gamma) -// -// screencapture -// - -FileWriter *OutputFileCounter::opennextfile(char *fn, char *zeros) -{ - do // JBF 2004022: So we don't overwrite existing screenshots - { - if (count > 9999) return nullptr; - - zeros[0] = ((count/1000)%10)+'0'; - zeros[1] = ((count/100)%10)+'0'; - zeros[2] = ((count/10)%10)+'0'; - zeros[3] = (count%10)+'0'; - if (!FileExists(fn)) break; - count++; - } while (1); - - return FileWriter::Open(fn); -} - -FileWriter *OutputFileCounter::opennextfile_withext(char *fn, const char *ext) -{ - char *dot = strrchr(fn, '.'); - strcpy(dot+1, ext); - return opennextfile(fn, dot-4); -} - -static OutputFileCounter capturecounter; - -# ifdef USE_OPENGL -# define HICOLOR (videoGetRenderMode() >= REND_POLYMOST && in3dmode()) -# else -# define HICOLOR 0 -# endif - -void getScreen(uint8_t* imgBuf) -{ - GLInterface.ReadPixels(xdim, ydim, imgBuf); -} - - -CVAR(String, screenshotname, "", CVAR_ARCHIVE) // not GLOBALCONFIG - allow setting this per game. -CVAR(String, screenshot_dir, "", CVAR_ARCHIVE) // same here. - -// -// WritePNGfile -// -void WritePNGfile(FileWriter* file, const uint8_t* buffer, const PalEntry* palette, - ESSType color_type, int width, int height, int pitch, float gamma) -{ - FStringf software("Demolition %s", GetVersionString()); - if (!M_CreatePNG(file, buffer, palette, color_type, width, height, pitch, gamma) || - !M_AppendPNGText(file, "Software", software) || - !M_FinishPNG(file)) - { - Printf("Failed writing screenshot\n"); - } -} - - -int videoCaptureScreen() -{ - PalEntry Palette[256]; - - size_t dirlen; - FString autoname = Args->CheckValue("-shotdir"); - if (autoname.IsEmpty()) - { - autoname = screenshot_dir; - } - dirlen = autoname.Len(); - if (dirlen == 0) - { - autoname = M_GetScreenshotsPath(); - dirlen = autoname.Len(); - } - if (dirlen > 0) - { - if (autoname[dirlen - 1] != '/' && autoname[dirlen - 1] != '\\') - { - autoname += '/'; - } - } - autoname = NicePath(autoname); - CreatePath(autoname); - - if (**screenshotname) autoname << screenshotname; - else autoname << currentGame; - autoname << "_0000"; - char* fn = autoname.LockBuffer(); - FileWriter *fil = capturecounter.opennextfile_withext(fn, "png"); - autoname.UnlockBuffer(); - - if (fil == nullptr) - { - return -1; - } - - uint8_t * const imgBuf = (uint8_t *) Xmalloc(xdim * ydim * (HICOLOR ? 3 : 1)); - - videoBeginDrawing(); //{{{ - - if (HICOLOR) - { - getScreen(imgBuf); - int const bytesPerLine = xdim * 3; - - // flip rows - uint8_t* rowBuf = (uint8_t *) Xmalloc(bytesPerLine); - - for (int i = 0, numRows = ydim >> 1; i < numRows; ++i) - { - memcpy(rowBuf, imgBuf + i * bytesPerLine, bytesPerLine); - memcpy(imgBuf + i * bytesPerLine, imgBuf + (ydim - i - 1) * bytesPerLine, bytesPerLine); - memcpy(imgBuf + (ydim - i - 1) * bytesPerLine, rowBuf, bytesPerLine); - } - - Xfree(rowBuf); - } - else - { - for (bssize_t i = 0; i < 256; ++i) - { - Palette[i].r = curpalettefaded[i].r; - Palette[i].g = curpalettefaded[i].g; - Palette[i].b = curpalettefaded[i].b; - } - - for (int i = 0; i < ydim; ++i) - Bmemcpy(imgBuf + i * xdim, (uint8_t *)frameplace + ylookup[i], xdim); - } - - videoEndDrawing(); //}}} - - WritePNGfile(fil, imgBuf, Palette, HICOLOR ? SS_RGB : SS_PAL, xdim, ydim, HICOLOR? xdim*3 : xdim, png_gamma); - delete fil; - Xfree(imgBuf); - Printf("Saved screenshot to %s\n", fn); - capturecounter.count++; - - return 0; -} - -CCMD(screenshot) -{ - videoCaptureScreen(); -} - -#undef HICOLOR - diff --git a/source/build/src/sdlayer.cpp b/source/build/src/sdlayer.cpp index 98ff65568..b3c2fad93 100644 --- a/source/build/src/sdlayer.cpp +++ b/source/build/src/sdlayer.cpp @@ -10,7 +10,7 @@ #include "a.h" #include "build.h" -#include "cache1d.h" + #include "common.h" #include "compat.h" #include "engine_priv.h" @@ -78,6 +78,8 @@ double g_beforeSwapTime; GameInterface* gi; FArgs* Args; +void buildkeytranslationtable();; + #if !defined STARTUP_SETUP_WINDOW int32_t startwin_open(void) { return 0; } int32_t startwin_close(void) { return 0; } @@ -143,7 +145,6 @@ static int32_t vsync_renderlayer; //#define KEY_PRINT_DEBUG -#include "sdlkeytrans.cpp" static SDL_Surface *appicon = NULL; #if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES @@ -377,7 +378,7 @@ void wm_setapptitle(const char *name) # include #endif -static inline char grabmouse_low(char a); +char grabmouse_low(char a); #ifndef __ANDROID__ static void attach_debugger_here(void) {} @@ -924,77 +925,6 @@ const char *joyGetName(int32_t what, int32_t num) } -// -// initmouse() -- init mouse input -// -void mouseInit(void) -{ - mouseGrabInput(g_mouseEnabled = g_mouseLockedToWindow); // FIXME - SA -} - -// -// uninitmouse() -- uninit mouse input -// -void mouseUninit(void) -{ - mouseGrabInput(0); - g_mouseEnabled = 0; -} - - -// -// grabmouse_low() -- show/hide mouse cursor, lower level (doesn't check state). -// furthermore return 0 if successful. -// - -static inline char grabmouse_low(char a) -{ - /* FIXME: Maybe it's better to make sure that grabmouse_low - is called only when a window is ready? */ - if (sdl_window) - SDL_SetWindowGrab(sdl_window, a ? SDL_TRUE : SDL_FALSE); - return SDL_SetRelativeMouseMode(a ? SDL_TRUE : SDL_FALSE); -} - -// -// grabmouse() -- show/hide mouse cursor -// -void mouseGrabInput(bool grab) -{ - if (appactive && g_mouseEnabled) - { - if ((grab != g_mouseGrabbed) && !grabmouse_low(grab)) - g_mouseGrabbed = grab; - } - else - g_mouseGrabbed = grab; - - inputState.MouseSetPos(0, 0); - SDL_ShowCursor(!grab ? SDL_ENABLE : SDL_DISABLE); - if (grab) GUICapture &= ~1; - else GUICapture |= 1; -} - -// -// setjoydeadzone() -- sets the dead and saturation zones for the joystick -// -void joySetDeadZone(int32_t axis, uint16_t dead, uint16_t satur) -{ - joydead[axis] = dead; - joysatur[axis] = satur; -} - - -// -// getjoydeadzone() -- gets the dead and saturation zones for the joystick -// -void joyGetDeadZone(int32_t axis, uint16_t *dead, uint16_t *satur) -{ - *dead = joydead[axis]; - *satur = joysatur[axis]; -} - - // // // --------------------------------------- @@ -1026,6 +956,20 @@ static int sortmodes(const void *a_, const void *b_) static char modeschecked=0; +void WindowMoved(int x, int y) +{ + if (windowpos) + { + windowx = x; + windowy = y; + } + + r_displayindex = SDL_GetWindowDisplayIndex(sdl_window); + modeschecked = 0; + videoGetModes(); +} + + #if SDL_MAJOR_VERSION != 1 void videoGetModes(void) { @@ -1606,493 +1550,6 @@ static inline SDL_Surface *loadappicon(void) // // -int32_t handleevents_peekkeys(void) -{ - SDL_PumpEvents(); - - return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYDOWN); -} - -static void PostMouseMove(int x, int y) -{ - static int lastx = 0, lasty = 0; - event_t ev = { 0,0,0,0,0,0,0 }; - - ev.x = x; - ev.y = y; - lastx = x; - lasty = y; - if (ev.x | ev.y) - { - ev.type = EV_Mouse; - D_PostEvent(&ev); - } -} - -CVAR(Bool, m_noprescale, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) - -static void MouseRead() -{ - int x, y; - -#if 0 - if (NativeMouse) - { - return; - } -#endif - - SDL_GetRelativeMouseState(&x, &y); - if (!m_noprescale) - { - x *= 3; - y *= 2; - } - if (x | y) - { - PostMouseMove(x, -y); - } -} - - -// -// handleevents() -- process the SDL message queue -// returns !0 if there was an important event worth checking (like quitting) -// - -int32_t handleevents_sdlcommon(SDL_Event *ev) -{ - switch (ev->type) - { - case SDL_MOUSEMOTION: - //case SDL_JOYBALLMOTION: - { - // The menus need this, even in non GUI-capture mode - event_t event; - event.data1 = ev->motion.x; - event.data2 = ev->motion.y; - - //screen->ScaleCoordsFromWindow(event.data1, event.data2); - - event.type = EV_GUI_Event; - event.subtype = EV_GUI_MouseMove; - - SDL_Keymod kmod = SDL_GetModState(); - event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | - ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | - ((kmod & KMOD_ALT) ? GKM_ALT : 0); - - D_PostEvent(&event); - break; - } - - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - { - int32_t j; - - // some of these get reordered to match winlayer - switch (ev->button.button) - { - default: j = -1; break; - case SDL_BUTTON_LEFT: j = KEY_MOUSE1; break; - case SDL_BUTTON_RIGHT: j = KEY_MOUSE2; break; - case SDL_BUTTON_MIDDLE: j = KEY_MOUSE3; break; - - /* Thumb buttons. */ - // On SDL2/Windows and SDL >= 2.0.?/Linux, everything is as it should be. - // If anyone cares about old versions of SDL2 on Linux, patches welcome. - case SDL_BUTTON_X1: j = KEY_MOUSE4; break; - case SDL_BUTTON_X2: j = KEY_MOUSE5; break; - } - - if (j < 0) - break; - - if (!(GUICapture & 1)) - { - event_t evt = { uint8_t((ev->button.state == SDL_PRESSED) ? EV_KeyDown : EV_KeyUp), 0, (int16_t)j }; - D_PostEvent(&evt); - } - else - { - event_t evt; - evt.type = EV_GUI_Event; - evt.subtype = uint8_t((ev->button.state == SDL_PRESSED) ? EV_GUI_LButtonDown : EV_GUI_LButtonUp); - evt.data1 = ev->motion.x; - evt.data2 = ev->motion.y; - - SDL_Keymod kmod = SDL_GetModState(); - evt.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | - ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | - ((kmod & KMOD_ALT) ? GKM_ALT : 0); - - D_PostEvent(&evt); - - } - break; - } - - case SDL_JOYAXISMOTION: -#if SDL_MAJOR_VERSION >= 2 - if (joystick.isGameController) - break; - fallthrough__; - case SDL_CONTROLLERAXISMOTION: -#endif - if (appactive && ev->jaxis.axis < joystick.numAxes) - { - joystick.pAxis[ev->jaxis.axis] = ev->jaxis.value; - int32_t const scaledValue = ev->jaxis.value * 10000 / 32767; - if ((scaledValue < joydead[ev->jaxis.axis]) && - (scaledValue > -joydead[ev->jaxis.axis])) - joystick.pAxis[ev->jaxis.axis] = 0; - else if (scaledValue >= joysatur[ev->jaxis.axis]) - joystick.pAxis[ev->jaxis.axis] = 32767; - else if (scaledValue <= -joysatur[ev->jaxis.axis]) - joystick.pAxis[ev->jaxis.axis] = -32767; - else - joystick.pAxis[ev->jaxis.axis] = joystick.pAxis[ev->jaxis.axis] * 10000 / joysatur[ev->jaxis.axis]; - } - break; - - case SDL_JOYHATMOTION: - { - int32_t hatvals[16] = { - -1, // centre - 0, // up 1 - 9000, // right 2 - 4500, // up+right 3 - 18000, // down 4 - -1, // down+up!! 5 - 13500, // down+right 6 - -1, // down+right+up!! 7 - 27000, // left 8 - 27500, // left+up 9 - -1, // left+right!! 10 - -1, // left+right+up!! 11 - 22500, // left+down 12 - -1, // left+down+up!! 13 - -1, // left+down+right!! 14 - -1, // left+down+right+up!! 15 - }; - if (appactive && ev->jhat.hat < joystick.numHats) - joystick.pHat[ev->jhat.hat] = hatvals[ev->jhat.value & 15]; - break; - } - - case SDL_JOYBUTTONDOWN: - case SDL_JOYBUTTONUP: -#if SDL_MAJOR_VERSION >= 2 - if (joystick.isGameController) - break; - fallthrough__; - case SDL_CONTROLLERBUTTONDOWN: - case SDL_CONTROLLERBUTTONUP: -#endif - if (appactive && ev->jbutton.button < joystick.numButtons) - { - if (ev->jbutton.state == SDL_PRESSED) - joystick.bits |= 1 << ev->jbutton.button; - else - joystick.bits &= ~(1 << ev->jbutton.button); - - } - break; - - case SDL_QUIT: - throw ExitEvent(0); // completely bypass the hackery in the games to block Alt-F4. - return -1; - } - - return 0; -} - -// So this is how the engine handles text input? -// Argh. This is just gross. -int scancodetoasciihack(SDL_Event &ev) -{ - int sc = ev.key.keysym.scancode; - SDL_Keycode keyvalue = ev.key.keysym.sym; - int code = keytranslation[sc]; - // Modifiers that have to be held down to be effective - // (excludes KMOD_NUM, for example). - static const int MODIFIERS = - KMOD_LSHIFT|KMOD_RSHIFT|KMOD_LCTRL|KMOD_RCTRL| - KMOD_LALT|KMOD_RALT|KMOD_LGUI|KMOD_RGUI; - - // XXX: see osd.c, OSD_HandleChar(), there are more... - if ( - (sc == SDL_SCANCODE_RETURN || sc == SDL_SCANCODE_KP_ENTER || - sc == SDL_SCANCODE_ESCAPE || - sc == SDL_SCANCODE_BACKSPACE || - sc == SDL_SCANCODE_TAB || - (((ev.key.keysym.mod) & MODIFIERS) == KMOD_LCTRL && - (sc >= SDL_SCANCODE_A && sc <= SDL_SCANCODE_Z)))) - { - char keyvalue; - switch (sc) - { - case SDL_SCANCODE_RETURN: case SDL_SCANCODE_KP_ENTER: keyvalue = '\r'; break; - case SDL_SCANCODE_ESCAPE: keyvalue = 27; break; - case SDL_SCANCODE_BACKSPACE: keyvalue = '\b'; break; - case SDL_SCANCODE_TAB: keyvalue = '\t'; break; - default: keyvalue = sc - SDL_SCANCODE_A + 1; break; // Ctrl+A --> 1, etc. - } - } - else - { - /* - Necessary for Duke 3D's method of entering cheats to work without showing IMEs. - SDL_TEXTINPUT is preferable overall, but with bitmap fonts it has no advantage. - */ - // Note that this is not how text input is supposed to be handled! - - if ('a' <= keyvalue && keyvalue <= 'z') - { - if (!!(ev.key.keysym.mod & KMOD_SHIFT) ^ !!(ev.key.keysym.mod & KMOD_CAPS)) - keyvalue -= 'a'-'A'; - } - else if (ev.key.keysym.mod & KMOD_SHIFT) - { - keyvalue = g_keyAsciiTableShift[code]; - } - else if (ev.key.keysym.mod & KMOD_NUM) // && !(ev.key.keysym.mod & KMOD_SHIFT) - { - switch (keyvalue) - { - case SDLK_KP_1: keyvalue = '1'; break; - case SDLK_KP_2: keyvalue = '2'; break; - case SDLK_KP_3: keyvalue = '3'; break; - case SDLK_KP_4: keyvalue = '4'; break; - case SDLK_KP_5: keyvalue = '5'; break; - case SDLK_KP_6: keyvalue = '6'; break; - case SDLK_KP_7: keyvalue = '7'; break; - case SDLK_KP_8: keyvalue = '8'; break; - case SDLK_KP_9: keyvalue = '9'; break; - case SDLK_KP_0: keyvalue = '0'; break; - case SDLK_KP_PERIOD: keyvalue = '.'; break; - case SDLK_KP_COMMA: keyvalue = ','; break; - } - } - - switch (keyvalue) - { - case SDLK_KP_DIVIDE: keyvalue = '/'; break; - case SDLK_KP_MULTIPLY: keyvalue = '*'; break; - case SDLK_KP_MINUS: keyvalue = '-'; break; - case SDLK_KP_PLUS: keyvalue = '+'; break; - } - } - if (keyvalue >= 0x80) keyvalue = 0; // Sadly ASCII only... - return keyvalue; -} - -int32_t handleevents_pollsdl(void); -#if SDL_MAJOR_VERSION != 1 -// SDL 2.0 specific event handling -int32_t handleevents_pollsdl(void) -{ - int32_t code, rv=0, j; - SDL_Event ev; - - while (SDL_PollEvent(&ev)) - { - if ((GUICapture & 10) == 2) - { - if (ImGui_ImplSDL2_ProcessEvent(&ev)) return 0; - } - switch (ev.type) - { - case SDL_TEXTINPUT: - { - j = 0; - const uint8_t* text = (uint8_t*)ev.text.text; - while ((j = GetCharFromString(text))) - { - code = ev.text.text[j]; - // Fixme: Send an EV_GUI_Event instead and properly deal with Unicode. - if ((GUICapture & 1) && menuactive != MENU_WaitKey) - { - event_t ev = { EV_GUI_Event, EV_GUI_Char, int16_t(j), !!(SDL_GetModState() & KMOD_ALT) }; - D_PostEvent(&ev); - } - } - break; - } - - case SDL_KEYDOWN: - case SDL_KEYUP: - { - if ((GUICapture & 1) && menuactive != MENU_WaitKey) - { - event_t event = {}; - event.type = EV_GUI_Event; - event.subtype = ev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp; - SDL_Keymod kmod = SDL_GetModState(); - event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | - ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | - ((kmod & KMOD_ALT) ? GKM_ALT : 0); - - if (event.subtype == EV_GUI_KeyDown && ev.key.repeat) - { - event.subtype = EV_GUI_KeyRepeat; - } - - switch (ev.key.keysym.sym) - { - case SDLK_KP_ENTER: event.data1 = GK_RETURN; break; - case SDLK_PAGEUP: event.data1 = GK_PGUP; break; - case SDLK_PAGEDOWN: event.data1 = GK_PGDN; break; - case SDLK_END: event.data1 = GK_END; break; - case SDLK_HOME: event.data1 = GK_HOME; break; - case SDLK_LEFT: event.data1 = GK_LEFT; break; - case SDLK_RIGHT: event.data1 = GK_RIGHT; break; - case SDLK_UP: event.data1 = GK_UP; break; - case SDLK_DOWN: event.data1 = GK_DOWN; break; - case SDLK_DELETE: event.data1 = GK_DEL; break; - case SDLK_ESCAPE: event.data1 = GK_ESCAPE; break; - case SDLK_F1: event.data1 = GK_F1; break; - case SDLK_F2: event.data1 = GK_F2; break; - case SDLK_F3: event.data1 = GK_F3; break; - case SDLK_F4: event.data1 = GK_F4; break; - case SDLK_F5: event.data1 = GK_F5; break; - case SDLK_F6: event.data1 = GK_F6; break; - case SDLK_F7: event.data1 = GK_F7; break; - case SDLK_F8: event.data1 = GK_F8; break; - case SDLK_F9: event.data1 = GK_F9; break; - case SDLK_F10: event.data1 = GK_F10; break; - case SDLK_F11: event.data1 = GK_F11; break; - case SDLK_F12: event.data1 = GK_F12; break; - default: - if (ev.key.keysym.sym < 256) - { - event.data1 = ev.key.keysym.sym; - } - break; - } - if (event.data1 < 128) - { - event.data1 = toupper(event.data1); - D_PostEvent(&event); - } - } - else - { - auto const& sc = ev.key.keysym.scancode; - code = keytranslation[sc]; - - // The pause key generates a release event right after - // the pressing one. As a result, it gets unseen - // by the game most of the time. - if (code == 0x59 && ev.type == SDL_KEYUP) // pause - break; - - int keyvalue = ev.type == SDL_KEYDOWN ? scancodetoasciihack(ev) : 0; - event_t evt = { (uint8_t)(ev.type == SDL_KEYUP ? EV_KeyUp : EV_KeyDown), 0, (int16_t)code, (int16_t)keyvalue }; - D_PostEvent(&evt); - } - - break; - } - - case SDL_MOUSEWHEEL: - // initprintf("wheel y %d\n",ev.wheel.y); - - // This never sends keyup events. For the current code that should suffice - if (ev.wheel.y > 0) - { - event_t evt = { EV_KeyDown, 0, (int16_t)KEY_MWHEELUP }; - D_PostEvent(&evt); - } - if (ev.wheel.y < 0) - { - event_t evt = { EV_KeyDown, 0, (int16_t)KEY_MWHEELDOWN }; - D_PostEvent(&evt); - } - break; - - case SDL_WINDOWEVENT: - switch (ev.window.event) - { - case SDL_WINDOWEVENT_FOCUS_GAINED: - case SDL_WINDOWEVENT_FOCUS_LOST: - appactive = (ev.window.event == SDL_WINDOWEVENT_FOCUS_GAINED); - if (g_mouseGrabbed && g_mouseEnabled) - grabmouse_low(appactive); - break; - - case SDL_WINDOWEVENT_MOVED: - { - if (windowpos) - { - windowx = ev.window.data1; - windowy = ev.window.data2; - } - - r_displayindex = SDL_GetWindowDisplayIndex(sdl_window); - modeschecked = 0; - videoGetModes(); - break; - } - case SDL_WINDOWEVENT_ENTER: - g_mouseInsideWindow = 1; - break; - case SDL_WINDOWEVENT_LEAVE: - g_mouseInsideWindow = 0; - break; - } - - break; - - default: - rv = handleevents_sdlcommon(&ev); - break; - } - } - MouseRead(); - - return rv; -} -#endif - -int32_t handleevents(void) -{ - int32_t rv; - - if (inputchecked && g_mouseEnabled) - { - // This is a horrible crutch - if (inputState.mouseReadButtons() & WHEELUP_MOUSE) - { - event_t ev = { EV_KeyUp, 0, (int16_t)KEY_MWHEELUP }; - D_PostEvent(&ev); - } - if (inputState.mouseReadButtons() & WHEELDOWN_MOUSE) - { - event_t ev = { EV_KeyUp, 0, (int16_t)KEY_MWHEELDOWN }; - D_PostEvent(&ev); - } - } - - rv = handleevents_pollsdl(); - - inputchecked = 0; - timerUpdateClock(); - return rv; -} - -void I_SetMouseCapture() -{ - // Clear out any mouse movement. - SDL_CaptureMouse(SDL_TRUE); -} - -void I_ReleaseMouseCapture() -{ - SDL_CaptureMouse(SDL_FALSE); -} - auto vsnprintfptr = vsnprintf; // This is an inline in Visual Studio but we need an address for it to satisfy the MinGW compiled libraries. // diff --git a/source/build/src/sdlkeytrans.cpp b/source/build/src/sdlkeytrans.cpp deleted file mode 100644 index 9cdd18ce7..000000000 --- a/source/build/src/sdlkeytrans.cpp +++ /dev/null @@ -1,263 +0,0 @@ - -#if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3) -static uint8_t keytranslation[SDLK_LAST]; -#else -static uint8_t keytranslation[SDL_NUM_SCANCODES]; -#endif -static int32_t buildkeytranslationtable(void); - -#if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3) // SDL 1.2 -static int32_t buildkeytranslationtable(void) -{ - memset(keytranslation,0,sizeof(keytranslation)); - -#define MAP(x,y) keytranslation[x] = y - MAP(SDLK_BACKSPACE, 0xe); - MAP(SDLK_TAB, 0xf); - MAP(SDLK_RETURN, 0x1c); - MAP(SDLK_PAUSE, 0x59); // 0x1d + 0x45 + 0x9d + 0xc5 - MAP(SDLK_ESCAPE, 0x1); - MAP(SDLK_SPACE, 0x39); - MAP(SDLK_EXCLAIM, 0x2); // '1' - MAP(SDLK_QUOTEDBL, 0x28); // ''' - MAP(SDLK_HASH, 0x4); // '3' - MAP(SDLK_DOLLAR, 0x5); // '4' - MAP(37, 0x6); // '5' <-- where's the keysym SDL guys? - MAP(SDLK_AMPERSAND, 0x8); // '7' - MAP(SDLK_QUOTE, 0x28); // ''' - MAP(SDLK_LEFTPAREN, 0xa); // '9' - MAP(SDLK_RIGHTPAREN, 0xb); // '0' - MAP(SDLK_ASTERISK, 0x9); // '8' - MAP(SDLK_PLUS, 0xd); // '=' - MAP(SDLK_COMMA, 0x33); - MAP(SDLK_MINUS, 0xc); - MAP(SDLK_PERIOD, 0x34); - MAP(SDLK_SLASH, 0x35); - MAP(SDLK_0, 0xb); - MAP(SDLK_1, 0x2); - MAP(SDLK_2, 0x3); - MAP(SDLK_3, 0x4); - MAP(SDLK_4, 0x5); - MAP(SDLK_5, 0x6); - MAP(SDLK_6, 0x7); - MAP(SDLK_7, 0x8); - MAP(SDLK_8, 0x9); - MAP(SDLK_9, 0xa); - MAP(SDLK_COLON, 0x27); - MAP(SDLK_SEMICOLON, 0x27); - MAP(SDLK_LESS, 0x56); - MAP(SDLK_EQUALS, 0xd); - MAP(SDLK_GREATER, 0x34); - MAP(SDLK_QUESTION, 0x35); - MAP(SDLK_AT, 0x3); // '2' - MAP(SDLK_LEFTBRACKET, 0x1a); - MAP(SDLK_BACKSLASH, 0x2b); - MAP(SDLK_RIGHTBRACKET, 0x1b); - MAP(SDLK_CARET, 0x7); // '7' - MAP(SDLK_UNDERSCORE, 0xc); - MAP(SDLK_BACKQUOTE, 0x29); - MAP(SDLK_a, 0x1e); - MAP(SDLK_b, 0x30); - MAP(SDLK_c, 0x2e); - MAP(SDLK_d, 0x20); - MAP(SDLK_e, 0x12); - MAP(SDLK_f, 0x21); - MAP(SDLK_g, 0x22); - MAP(SDLK_h, 0x23); - MAP(SDLK_i, 0x17); - MAP(SDLK_j, 0x24); - MAP(SDLK_k, 0x25); - MAP(SDLK_l, 0x26); - MAP(SDLK_m, 0x32); - MAP(SDLK_n, 0x31); - MAP(SDLK_o, 0x18); - MAP(SDLK_p, 0x19); - MAP(SDLK_q, 0x10); - MAP(SDLK_r, 0x13); - MAP(SDLK_s, 0x1f); - MAP(SDLK_t, 0x14); - MAP(SDLK_u, 0x16); - MAP(SDLK_v, 0x2f); - MAP(SDLK_w, 0x11); - MAP(SDLK_x, 0x2d); - MAP(SDLK_y, 0x15); - MAP(SDLK_z, 0x2c); - MAP(SDLK_DELETE, 0xd3); - MAP(SDLK_KP0, 0x52); - MAP(SDLK_KP1, 0x4f); - MAP(SDLK_KP2, 0x50); - MAP(SDLK_KP3, 0x51); - MAP(SDLK_KP4, 0x4b); - MAP(SDLK_KP5, 0x4c); - MAP(SDLK_KP6, 0x4d); - MAP(SDLK_KP7, 0x47); - MAP(SDLK_KP8, 0x48); - MAP(SDLK_KP9, 0x49); - MAP(SDLK_KP_PERIOD, 0x53); - MAP(SDLK_KP_DIVIDE, 0xb5); - MAP(SDLK_KP_MULTIPLY, 0x37); - MAP(SDLK_KP_MINUS, 0x4a); - MAP(SDLK_KP_PLUS, 0x4e); - MAP(SDLK_KP_ENTER, 0x9c); - //MAP(SDLK_KP_EQUALS, ); - MAP(SDLK_UP, 0xc8); - MAP(SDLK_DOWN, 0xd0); - MAP(SDLK_RIGHT, 0xcd); - MAP(SDLK_LEFT, 0xcb); - MAP(SDLK_INSERT, 0xd2); - MAP(SDLK_HOME, 0xc7); - MAP(SDLK_END, 0xcf); - MAP(SDLK_PAGEUP, 0xc9); - MAP(SDLK_PAGEDOWN, 0xd1); - MAP(SDLK_F1, 0x3b); - MAP(SDLK_F2, 0x3c); - MAP(SDLK_F3, 0x3d); - MAP(SDLK_F4, 0x3e); - MAP(SDLK_F5, 0x3f); - MAP(SDLK_F6, 0x40); - MAP(SDLK_F7, 0x41); - MAP(SDLK_F8, 0x42); - MAP(SDLK_F9, 0x43); - MAP(SDLK_F10, 0x44); - MAP(SDLK_F11, 0x57); - MAP(SDLK_F12, 0x58); - MAP(SDLK_NUMLOCK, 0x45); - MAP(SDLK_CAPSLOCK, 0x3a); - MAP(SDLK_SCROLLOCK, 0x46); - MAP(SDLK_RSHIFT, 0x36); - MAP(SDLK_LSHIFT, 0x2a); - MAP(SDLK_RCTRL, 0x9d); - MAP(SDLK_LCTRL, 0x1d); - MAP(SDLK_RALT, 0xb8); - MAP(SDLK_LALT, 0x38); - MAP(SDLK_LSUPER, 0xdb); // win l - MAP(SDLK_RSUPER, 0xdc); // win r - MAP(SDLK_PRINT, -2); // 0xaa + 0xb7 - MAP(SDLK_SYSREQ, 0x54); // alt+printscr - MAP(SDLK_BREAK, 0xb7); // ctrl+pause - MAP(SDLK_MENU, 0xdd); // win menu? -#undef MAP - - return 0; -} -#else // if SDL 1.3+ -static int32_t buildkeytranslationtable(void) -{ - memset(keytranslation,0,sizeof(keytranslation)); - -#define MAP(x,y) keytranslation[x] = y - MAP(SDL_SCANCODE_BACKSPACE, 0xe); - MAP(SDL_SCANCODE_TAB, 0xf); - MAP(SDL_SCANCODE_RETURN, 0x1c); - MAP(SDL_SCANCODE_PAUSE, 0x59); // 0x1d + 0x45 + 0x9d + 0xc5 - MAP(SDL_SCANCODE_ESCAPE, 0x1); - MAP(SDL_SCANCODE_SPACE, 0x39); - MAP(SDL_SCANCODE_COMMA, 0x33); - MAP(SDL_SCANCODE_NONUSBACKSLASH, 0x56); - MAP(SDL_SCANCODE_MINUS, 0xc); - MAP(SDL_SCANCODE_PERIOD, 0x34); - MAP(SDL_SCANCODE_SLASH, 0x35); - MAP(SDL_SCANCODE_0, 0xb); - MAP(SDL_SCANCODE_1, 0x2); - MAP(SDL_SCANCODE_2, 0x3); - MAP(SDL_SCANCODE_3, 0x4); - MAP(SDL_SCANCODE_4, 0x5); - MAP(SDL_SCANCODE_5, 0x6); - MAP(SDL_SCANCODE_6, 0x7); - MAP(SDL_SCANCODE_7, 0x8); - MAP(SDL_SCANCODE_8, 0x9); - MAP(SDL_SCANCODE_9, 0xa); - MAP(SDL_SCANCODE_SEMICOLON, 0x27); - MAP(SDL_SCANCODE_APOSTROPHE, 0x28); - MAP(SDL_SCANCODE_EQUALS, 0xd); - MAP(SDL_SCANCODE_LEFTBRACKET, 0x1a); - MAP(SDL_SCANCODE_BACKSLASH, 0x2b); - MAP(SDL_SCANCODE_RIGHTBRACKET, 0x1b); - MAP(SDL_SCANCODE_A, 0x1e); - MAP(SDL_SCANCODE_B, 0x30); - MAP(SDL_SCANCODE_C, 0x2e); - MAP(SDL_SCANCODE_D, 0x20); - MAP(SDL_SCANCODE_E, 0x12); - MAP(SDL_SCANCODE_F, 0x21); - MAP(SDL_SCANCODE_G, 0x22); - MAP(SDL_SCANCODE_H, 0x23); - MAP(SDL_SCANCODE_I, 0x17); - MAP(SDL_SCANCODE_J, 0x24); - MAP(SDL_SCANCODE_K, 0x25); - MAP(SDL_SCANCODE_L, 0x26); - MAP(SDL_SCANCODE_M, 0x32); - MAP(SDL_SCANCODE_N, 0x31); - MAP(SDL_SCANCODE_O, 0x18); - MAP(SDL_SCANCODE_P, 0x19); - MAP(SDL_SCANCODE_Q, 0x10); - MAP(SDL_SCANCODE_R, 0x13); - MAP(SDL_SCANCODE_S, 0x1f); - MAP(SDL_SCANCODE_T, 0x14); - MAP(SDL_SCANCODE_U, 0x16); - MAP(SDL_SCANCODE_V, 0x2f); - MAP(SDL_SCANCODE_W, 0x11); - MAP(SDL_SCANCODE_X, 0x2d); - MAP(SDL_SCANCODE_Y, 0x15); - MAP(SDL_SCANCODE_Z, 0x2c); - MAP(SDL_SCANCODE_DELETE, 0xd3); - MAP(SDL_SCANCODE_KP_0, 0x52); - MAP(SDL_SCANCODE_KP_1, 0x4f); - MAP(SDL_SCANCODE_KP_2, 0x50); - MAP(SDL_SCANCODE_KP_3, 0x51); - MAP(SDL_SCANCODE_KP_4, 0x4b); - MAP(SDL_SCANCODE_KP_5, 0x4c); - MAP(SDL_SCANCODE_KP_CLEAR, 0x4c); - MAP(SDL_SCANCODE_CLEAR, 0x4c); - MAP(SDL_SCANCODE_KP_6, 0x4d); - MAP(SDL_SCANCODE_KP_7, 0x47); - MAP(SDL_SCANCODE_KP_8, 0x48); - MAP(SDL_SCANCODE_KP_9, 0x49); - MAP(SDL_SCANCODE_KP_PERIOD, 0x53); - MAP(SDL_SCANCODE_KP_DIVIDE, 0xb5); - MAP(SDL_SCANCODE_KP_MULTIPLY, 0x37); - MAP(SDL_SCANCODE_KP_MINUS, 0x4a); - MAP(SDL_SCANCODE_KP_PLUS, 0x4e); - MAP(SDL_SCANCODE_KP_ENTER, 0x9c); - //MAP(SDL_SCANCODE_KP_EQUALS, ); - MAP(SDL_SCANCODE_UP, 0xc8); - MAP(SDL_SCANCODE_DOWN, 0xd0); - MAP(SDL_SCANCODE_RIGHT, 0xcd); - MAP(SDL_SCANCODE_LEFT, 0xcb); - MAP(SDL_SCANCODE_INSERT, 0xd2); - MAP(SDL_SCANCODE_HOME, 0xc7); - MAP(SDL_SCANCODE_END, 0xcf); - MAP(SDL_SCANCODE_PAGEUP, 0xc9); - MAP(SDL_SCANCODE_PAGEDOWN, 0xd1); - MAP(SDL_SCANCODE_F1, 0x3b); - MAP(SDL_SCANCODE_F2, 0x3c); - MAP(SDL_SCANCODE_F3, 0x3d); - MAP(SDL_SCANCODE_F4, 0x3e); - MAP(SDL_SCANCODE_F5, 0x3f); - MAP(SDL_SCANCODE_F6, 0x40); - MAP(SDL_SCANCODE_F7, 0x41); - MAP(SDL_SCANCODE_F8, 0x42); - MAP(SDL_SCANCODE_F9, 0x43); - MAP(SDL_SCANCODE_F10, 0x44); - MAP(SDL_SCANCODE_F11, 0x57); - MAP(SDL_SCANCODE_F12, 0x58); - MAP(SDL_SCANCODE_NUMLOCKCLEAR, 0x45); - MAP(SDL_SCANCODE_CAPSLOCK, 0x3a); - MAP(SDL_SCANCODE_SCROLLLOCK, 0x46); - MAP(SDL_SCANCODE_RSHIFT, 0x36); - MAP(SDL_SCANCODE_LSHIFT, 0x2a); - MAP(SDL_SCANCODE_RCTRL, 0x9d); - MAP(SDL_SCANCODE_LCTRL, 0x1d); - MAP(SDL_SCANCODE_RALT, 0xb8); - MAP(SDL_SCANCODE_LALT, 0x38); - MAP(SDL_SCANCODE_LGUI, 0xdb); // win l - MAP(SDL_SCANCODE_RGUI, 0xdc); // win r -// MAP(SDL_SCANCODE_PRINTSCREEN, -2); // 0xaa + 0xb7 - MAP(SDL_SCANCODE_SYSREQ, 0x54); // alt+printscr -// MAP(SDL_SCANCODE_PAUSE, 0xb7); // ctrl+pause - MAP(SDL_SCANCODE_MENU, 0xdd); // win menu? - MAP(SDL_SCANCODE_GRAVE, 0x29); // tilde -#undef MAP - - return 0; -} -#endif diff --git a/source/build/src/tiles.cpp b/source/build/src/tiles.cpp index 09b301025..4af93859d 100644 --- a/source/build/src/tiles.cpp +++ b/source/build/src/tiles.cpp @@ -10,7 +10,7 @@ #include "build.h" #include "baselayer.h" #include "engine_priv.h" -#include "cache1d.h" + // // copytilepiece diff --git a/source/build/src/voxmodel.cpp b/source/build/src/voxmodel.cpp index 112f1d1c8..2f0915a20 100644 --- a/source/build/src/voxmodel.cpp +++ b/source/build/src/voxmodel.cpp @@ -10,7 +10,7 @@ #include "hightile.h" #include "polymost.h" #include "mdsprite.h" -#include "cache1d.h" + #include "palette.h" #include "../../glbackend/glbackend.h" @@ -1091,8 +1091,7 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr) GLInterface.EnableBlend(true); // else GLInterface.EnableBlend(false); } else pc[3] = 1.f; - GLInterface.SetFadeDisable(true); // disable depth fading. The voxel code is somewhat broken and messes this up. - GLInterface.SetShade(0, numshades); + GLInterface.SetShade(std::max(0, globalshade), numshades); //------------ //transform to Build coords diff --git a/source/mact/src/animlib.cpp b/source/common/animlib.cpp similarity index 100% rename from source/mact/src/animlib.cpp rename to source/common/animlib.cpp diff --git a/source/mact/include/animlib.h b/source/common/animlib.h similarity index 100% rename from source/mact/include/animlib.h rename to source/common/animlib.h diff --git a/source/common/console/c_con.cpp b/source/common/console/c_con.cpp index df40bde31..a7db2650a 100644 --- a/source/common/console/c_con.cpp +++ b/source/common/console/c_con.cpp @@ -37,7 +37,6 @@ #include "basics.h" #include "zstring.h" #include "c_bind.h" -#include "control.h" #include "gamecontrol.h" //============================================================================= @@ -198,7 +197,7 @@ char const* C_CON_GetGameFuncOnJoystick(int gameFunc) FString C_CON_GetBoundKeyForLastInput(int gameFunc) { - if (CONTROL_LastSeenInput == LastSeenInput::Joystick) + if (inputState.gamePadActive()) { FString name = C_CON_GetGameFuncOnJoystick(gameFunc); if (name.IsNotEmpty()) diff --git a/source/common/console/d_event.cpp b/source/common/console/d_event.cpp index 03b424c8e..aa1772d18 100644 --- a/source/common/console/d_event.cpp +++ b/source/common/console/d_event.cpp @@ -105,8 +105,8 @@ void D_ProcessEvents (void) ev = &events[eventtail]; if (ev->type == EV_None) continue; - if (ev->type == EV_DeviceChange) - (void)0;//UpdateJoystickMenu(I_UpdateDeviceList()); + /*if (ev->type == EV_DeviceChange) + UpdateJoystickMenu(I_UpdateDeviceList());*/ if (C_Responder (ev)) continue; // console ate the event if (M_Responder (ev)) diff --git a/source/common/filesystem/filesystem.cpp b/source/common/filesystem/filesystem.cpp index b7bbee4e1..759cb4af0 100644 --- a/source/common/filesystem/filesystem.cpp +++ b/source/common/filesystem/filesystem.cpp @@ -550,6 +550,15 @@ int FileSystem::GetResourceId(int lump) const return FileInfo[lump].lump->ResourceId; } +FName FileSystem::GetResourceType(int lump) const +{ + if ((size_t)lump >= NumEntries) + return NAME_None; + else + return FileInfo[lump].lump->LumpName[FResourceLump::ExtensionType]; +} + + //========================================================================== // // GetLumpFile @@ -893,13 +902,14 @@ const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept // //========================================================================== -void FileSystem::AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags) +int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags) { FStringf fullname("%s.%s", name, type); auto newlump = new FMemoryLump(data, size); newlump->LumpNameSetup(fullname); newlump->ResourceId = id; AddLump(newlump); + return Files.Size()-1; } //========================================================================== diff --git a/source/common/filesystem/filesystem.h b/source/common/filesystem/filesystem.h index 028716c44..ae4a02db9 100644 --- a/source/common/filesystem/filesystem.h +++ b/source/common/filesystem/filesystem.h @@ -118,7 +118,7 @@ public: int FindResource (int resid, const char *type, int filenum = -1) const noexcept; int GetResource (int resid, const char *type, int filenum = -1) const; // Like FindFile, but throws an exception when it cannot find what it looks for. - void AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags); + int AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags); TArray GetAllFilesOfType(FName type, bool withsubdirs = false); @@ -164,6 +164,7 @@ public: bool IsEncryptedFile(int file) const noexcept; int GetResourceId(int file) const; + FName GetResourceType(int file) const; int GetNumResourceFiles() const { return NumFiles; } int GetNumEntries () const { return NumEntries; } diff --git a/source/common/filesystem/resourcefile.cpp b/source/common/filesystem/resourcefile.cpp index 446db0deb..ea64d6665 100644 --- a/source/common/filesystem/resourcefile.cpp +++ b/source/common/filesystem/resourcefile.cpp @@ -299,7 +299,6 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize) // each one so that we don't risk refiltering already filtered lumps. uint32_t max = NumLumps; - long len; int lastpos = -1; FString file; @@ -310,7 +309,7 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize) { if (build.IsEmpty()) build = segment; else build << "." << segment; - max -= FilterLumps(LumpFilter, lumps, lumpsize, max); + max -= FilterLumps(build, lumps, lumpsize, max); } JunkLeftoverFilters(lumps, lumpsize, max); } @@ -338,13 +337,6 @@ int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, bool found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); - // Workaround for old Doom filter names. - if (!found && filtername.IndexOf("doom.id.doom") == 0) - { - filter.Substitute("doom.id.doom", "doom.doom"); - found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); - } - if (found) { void *from = (uint8_t *)lumps + start * lumpsize; diff --git a/source/common/fonts/v_font.cpp b/source/common/fonts/v_font.cpp index a11beba66..50037405c 100644 --- a/source/common/fonts/v_font.cpp +++ b/source/common/fonts/v_font.cpp @@ -47,7 +47,7 @@ #include "v_text.h" #include "image.h" #include "utf8.h" -#include "cache1d.h" + #include "m_png.h" #include "printf.h" #include "filesystem.h" diff --git a/source/common/gameconfigfile.cpp b/source/common/gameconfigfile.cpp index e045c2645..e8c360aae 100644 --- a/source/common/gameconfigfile.cpp +++ b/source/common/gameconfigfile.cpp @@ -40,14 +40,7 @@ #include "c_bind.h" #include "m_argv.h" #include "cmdlib.h" -//#include "version.h" #include "i_specialpaths.h" -//#include "v_font.h" -//#include "doomstat.h" -//#include "gi.h" -//#include "d_main.h" -#include "keyboard.h" -#include "control.h" #include "printf.h" #include "gamecontrol.h" #include "version.h" @@ -531,7 +524,6 @@ void G_SaveConfig() { GameConfig->ArchiveGlobalData(); GameConfig->ArchiveGameData(GameName); - CONFIG_WriteControllerSettings(); GameConfig->WriteConfigFile(); delete GameConfig; GameConfig = nullptr; diff --git a/source/common/gamecontrol.cpp b/source/common/gamecontrol.cpp index 31fe9bf85..7b38b32c5 100644 --- a/source/common/gamecontrol.cpp +++ b/source/common/gamecontrol.cpp @@ -1,18 +1,36 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2019 Christoph Oelckers + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +//------------------------------------------------------------------------- + #include #include "gamecontrol.h" #include "tarray.h" #include "zstring.h" #include "name.h" -#include "control.h" -#include "keyboard.h" #include "sc_man.h" #include "c_cvars.h" #include "gameconfigfile.h" #include "gamecvars.h" #include "build.h" #include "inputstate.h" -#include "_control.h" -#include "control.h" #include "m_argv.h" #include "rts.h" #include "printf.h" @@ -27,6 +45,7 @@ #include "gstrings.h" #include "quotemgr.h" #include "mapinfo.h" +#include "s_soundinternal.h" #ifndef NETCODE_DISABLE #include "enet.h" #endif @@ -258,6 +277,16 @@ void CheckFrontend(int flags) } } +void I_StartupJoysticks(); +void I_ShutdownInput(); +int RunGame(); + +void ShutdownSystem() +{ + Mus_Stop(); + if (soundEngine) delete soundEngine; + I_ShutdownInput(); +} int GameMain() { @@ -265,6 +294,8 @@ int GameMain() C_InitConsole(1024, 768, true); FStringf logpath("logfile %sdemolition.log", M_GetDocumentsPath().GetChars()); C_DoCommand(logpath); + I_StartupJoysticks(); + mouseInit(); #ifndef NETCODE_DISABLE gHaveNetworking = !enet_initialize(); @@ -275,10 +306,12 @@ int GameMain() int r; try { - r = CONFIG_Init(); + r = RunGame(); } catch (const std::runtime_error & err) { + // shut down critical systems before showing a message box. + ShutdownSystem(); wm_msgbox("Error", "%s", err.what()); return 3; } @@ -287,6 +320,7 @@ int GameMain() // Just let the rest of the function execute. r = exit.Reason(); } + ShutdownSystem(); G_SaveConfig(); #ifndef NETCODE_DISABLE if (gHaveNetworking) enet_deinitialize(); @@ -321,13 +355,6 @@ void SetDefaultStrings() quoteMgr.InitializeQuote(84, "$FOLLOW MODE ON"); quoteMgr.InitializeQuote(85, "$AUTORUNOFF"); quoteMgr.InitializeQuote(86, "$AUTORUNON"); - #if 0 // todo: print a message - if (gAutoRun) - viewSetMessage("Auto run ON"); - else - viewSetMessage("Auto run OFF"); - - #endif } //========================================================================== @@ -336,16 +363,10 @@ void SetDefaultStrings() // //========================================================================== -int CONFIG_Init() +int RunGame() { SetClipshapes(); - // This must be done before initializing any data, so doing it late in the startup process won't work. - if (CONTROL_Startup(controltype_keyboardandmouse, BGetTime, 120)) - { - return 1; - } - userConfig.ProcessOptions(); G_LoadConfig(); @@ -442,9 +463,12 @@ int CONFIG_Init() addArt.Push(art); } } + if (userConfig.AddArt) for (auto& art : *userConfig.AddArt) + { + addArt.Push(art); + } TileFiles.AddArt(addArt); - CONTROL_ClearAssignments(); CONFIG_InitMouseAndController(); CONFIG_SetDefaultKeys(cl_defaultconfiguration == 1 ? "demolition/origbinds.txt" : cl_defaultconfiguration == 2 ? "demolition/leftbinds.txt" : "demolition/defbinds.txt"); @@ -461,11 +485,13 @@ int CONFIG_Init() GStrings.LoadStrings(); V_InitFonts(); C_CON_SetAliases(); + sfx_empty = fileSystem.FindFile("demolition/dsempty.lmp"); // this must be done outside the sound code because it's initialized late. Mus_Init(); InitStatistics(); M_Init(); SetDefaultStrings(); if (g_gameType & GAMEFLAG_RR) InitRREndMap(); // this needs to be done better later + //C_DoCommand("stat sounddebug"); return gi->app_main(); } @@ -541,288 +567,20 @@ int CONFIG_SetMapBestTime(uint8_t const* const mapmd4, int32_t tm) } return 0; } -//========================================================================== -// -// -// -//========================================================================== - -int32_t MouseAnalogueAxes[MAXMOUSEAXES]; -int32_t JoystickFunctions[MAXJOYBUTTONSANDHATS][2]; -int32_t JoystickDigitalFunctions[MAXJOYAXES][2]; -int32_t JoystickAnalogueAxes[MAXJOYAXES]; -int32_t JoystickAnalogueScale[MAXJOYAXES]; -int32_t JoystickAnalogueDead[MAXJOYAXES]; -int32_t JoystickAnalogueSaturate[MAXJOYAXES]; -int32_t JoystickAnalogueInvert[MAXJOYAXES]; - -static const char* mouseanalogdefaults[MAXMOUSEAXES] = -{ -"analog_turning", -"analog_moving", -}; - - -static const char* joystickclickeddefaults[MAXJOYBUTTONSANDHATS] = -{ -"", -"Inventory", -"Jump", -"Crouch", -}; - - -static const char* joystickanalogdefaults[MAXJOYAXES] = -{ -"analog_turning", -"analog_moving", -"analog_strafing", -}; - - -//========================================================================== -// -// -// -//========================================================================== - -int32_t CONFIG_AnalogNameToNum(const char* func) -{ - if (!func) - return -1; - - if (!Bstrcasecmp(func, "analog_turning")) - { - return analog_turning; - } - if (!Bstrcasecmp(func, "analog_strafing")) - { - return analog_strafing; - } - if (!Bstrcasecmp(func, "analog_moving")) - { - return analog_moving; - } - if (!Bstrcasecmp(func, "analog_lookingupanddown")) - { - return analog_lookingupanddown; - } - - return -1; -} - - -//========================================================================== -// -// -// -//========================================================================== - -const char* CONFIG_AnalogNumToName(int32_t func) -{ - switch (func) - { - case analog_turning: - return "analog_turning"; - case analog_strafing: - return "analog_strafing"; - case analog_moving: - return "analog_moving"; - case analog_lookingupanddown: - return "analog_lookingupanddown"; - } - - return NULL; -} - -void CONFIG_SetupMouse(void) -{ - CONTROL_MouseEnabled = (in_mouse && CONTROL_MousePresent); -} - - -void CONFIG_SetupJoystick(void) -{ - for (int i = 0; i < MAXJOYAXES; i++) - { - CONTROL_MapAnalogAxis(i, JoystickAnalogueAxes[i], controldevice_joystick); - CONTROL_MapDigitalAxis(i, JoystickDigitalFunctions[i][0], 0, controldevice_joystick); - CONTROL_MapDigitalAxis(i, JoystickDigitalFunctions[i][1], 1, controldevice_joystick); - CONTROL_SetAnalogAxisScale(i, JoystickAnalogueScale[i], controldevice_joystick); - CONTROL_SetAnalogAxisInvert(i, JoystickAnalogueInvert[i], controldevice_joystick); - } - - CONTROL_JoystickEnabled = (in_joystick && CONTROL_JoyPresent); - - // JBF 20040215: evil and nasty place to do this, but joysticks are evil and nasty too - for (int i=0; iSetValueForKey(key, str); + Mus_Stop(); + if (soundEngine) soundEngine->Reset(); + MUS_ResumeSaved(); } -void CONFIG_WriteControllerSettings() -{ - FString buf; - - - if (in_joystick) - { - FString section = currentGame + ".ControllerSettings"; - GameConfig->SetSection(section); - for (int dummy = 0; dummy < MAXJOYAXES; dummy++) - { - if (CONFIG_AnalogNumToName(JoystickAnalogueAxes[dummy])) - { - buf.Format("ControllerAnalogAxes%d", dummy); - GameConfig->SetValueForKey(buf, CONFIG_AnalogNumToName(JoystickAnalogueAxes[dummy])); - } - - if (buttonMap.GetButtonName(JoystickDigitalFunctions[dummy][1])) - { - buf.Format("ControllerDigitalAxes%d_1", dummy); - GameConfig->SetValueForKey(buf, buttonMap.GetButtonName(JoystickDigitalFunctions[dummy][1])); - } - - buf.Format("ControllerAnalogScale%d", dummy); - CONFIG_PutNumber(buf, JoystickAnalogueScale[dummy]); - - buf.Format("ControllerAnalogInvert%d", dummy); - CONFIG_PutNumber(buf, JoystickAnalogueInvert[dummy]); - - buf.Format("ControllerAnalogDead%d", dummy); - CONFIG_PutNumber(buf, JoystickAnalogueDead[dummy]); - - buf.Format("ControllerAnalogSaturate%d", dummy); - CONFIG_PutNumber(buf, JoystickAnalogueSaturate[dummy]); - } - } -} diff --git a/source/common/gamecontrol.h b/source/common/gamecontrol.h index 31955c8f1..c835934a6 100644 --- a/source/common/gamecontrol.h +++ b/source/common/gamecontrol.h @@ -1,8 +1,5 @@ #pragma once -#include "keyboard.h" -#include "control.h" -#include "_control.h" #include "c_cvars.h" #include "zstring.h" #include "inputstate.h" @@ -39,7 +36,6 @@ void CONFIG_SetDefaultKeys(const char *defbinds); void CONFIG_SetupJoystick(void); -void CONFIG_WriteControllerSettings(); void CONFIG_InitMouseAndController(); void CONFIG_SetGameControllerDefaultsClear(); diff --git a/source/common/gamecvars.cpp b/source/common/gamecvars.cpp index 5a4674b13..acc4deb61 100644 --- a/source/common/gamecvars.cpp +++ b/source/common/gamecvars.cpp @@ -36,12 +36,8 @@ #include "c_cvars.h" #include "common.h" -#include "fx_man.h" #include "baselayer.h" #include "gameconfigfile.h" -#include "keyboard.h" -#include "control.h" -#include "_control.h" #include "gamecontrol.h" #include "m_argv.h" #include "rts.h" @@ -99,7 +95,7 @@ CUSTOM_CVARD(Int, cl_crosshairscale, 50, CVAR_ARCHIVE, "changes the size of the CUSTOM_CVARD(Int, cl_autoaim, 1, CVAR_ARCHIVE|CVAR_USERINFO, "enable/disable weapon autoaim") { - if (self < 0 || self > (playing_blood? 2 : 3)) self = 1; // The Shadow Warrior backend only has a bool for this. + if (self < 0 || self > ((g_gameType & GAMEFLAG_BLOOD)? 2 : 3)) self = 1; // The Shadow Warrior backend only has a bool for this. //UpdatePlayerFromMenu(); todo: networking (only operational in EDuke32 frontend anyway.) }; @@ -107,7 +103,7 @@ CUSTOM_CVARD(Int, cl_weaponswitch, 3, CVAR_ARCHIVE|CVAR_USERINFO, "enable/disabl { if (self < 0) self = 0; - if (self > 3 && playing_blood) self = 3; + if (self > 3 && (g_gameType & GAMEFLAG_BLOOD)) self = 3; if (self > 7) self = 7; //UpdatePlayerFromMenu(); todo: networking (only operational in EDuke32 frontend anyway.) } @@ -141,11 +137,6 @@ CVARD(Bool, snd_doppler, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "enable/disable CVARD(Bool, mus_restartonload, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "restart the music when loading a saved game with the same map or not") // only implemented for Blood - todo: generalize CVARD(Bool, mus_redbook, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_FRONTEND_BLOOD, "enables/disables redbook audio (Blood only!)") // only Blood has assets for this. -CUSTOM_CVARD(Bool, snd_reversestereo, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL, "reverses the stereo channels") -{ - FX_SetReverseStereo(self); -} - CUSTOM_CVARD(Int, snd_fxvolume, 255, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls volume for sound effects") { if (self < 0) self = 0; @@ -292,16 +283,8 @@ CUSTOM_CVARD(Int, r_fov, 90, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "change the field o CVARD(Bool, r_horizcenter, false, CVAR_ARCHIVE|CVAR_FRONTEND_BLOOD, "enable/disable centered horizon line") // only present in Blood, maybe add to others? -CUSTOM_CVARD(Bool, in_joystick, false, CVAR_ARCHIVE||CVAR_GLOBALCONFIG|CVAR_NOINITCALL, "enables input from the joystick if it is present") -{ - CONTROL_JoystickEnabled = (self && CONTROL_JoyPresent); -} - -CUSTOM_CVARD(Bool, in_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL, "enables input from the mouse if it is present") -{ - CONTROL_MouseEnabled = (self && CONTROL_MousePresent); -} - +CVARD(Bool, in_joystick, false, CVAR_ARCHIVE||CVAR_GLOBALCONFIG|CVAR_NOINITCALL, "enables input from the joystick if it is present") +CVARD(Bool, in_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL, "enables input from the mouse if it is present") CVARD(Bool, in_mousemode, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "toggles vertical mouse view") CVAR(Bool, silentmouseaimtoggle, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) diff --git a/source/common/gamecvars.h b/source/common/gamecvars.h index 45463e313..d998bf466 100644 --- a/source/common/gamecvars.h +++ b/source/common/gamecvars.h @@ -40,7 +40,6 @@ EXTERN_CVAR(Bool, snd_doppler) EXTERN_CVAR(Bool, mus_enabled) EXTERN_CVAR(Bool, mus_restartonload) EXTERN_CVAR(Bool, mus_redbook) -EXTERN_CVAR(Bool, snd_reversestereo) EXTERN_CVAR(Int, snd_fxvolume) EXTERN_CVAR(Int, snd_mixrate) EXTERN_CVAR(Int, snd_numchannels) diff --git a/source/common/initfs.cpp b/source/common/initfs.cpp index 6f46b4892..0bb9a9ee9 100644 --- a/source/common/initfs.cpp +++ b/source/common/initfs.cpp @@ -327,7 +327,7 @@ void InitFileSystem(TArray& groups) { // Build's original 'file system' loads all GRPs before the first external directory. // Do this only if explicitly requested because this severely limits the usability of GRP files. - if (insertdirectoriesafter) for (auto& file : *userConfig.AddFilesPre) + if (insertdirectoriesafter && userConfig.AddFilesPre) for (auto& file : *userConfig.AddFilesPre) { D_AddFile(Files, '*' + file); // The * tells the file system not to pull in all subdirectories. } @@ -337,27 +337,30 @@ void InitFileSystem(TArray& groups) i--; } - if (!insertdirectoriesafter) for (auto& file : *userConfig.AddFilesPre) + if (!insertdirectoriesafter && userConfig.AddFilesPre) for (auto& file : *userConfig.AddFilesPre) { D_AddFile(Files, file); } - for (auto& file : *userConfig.AddFiles) + if (userConfig.AddFiles) { - D_AddFile(Files, file); - } - - // Finally, if the last entry in the chain is a directory, it's being considered the mod directory, and all GRPs inside need to be loaded, too. - if (userConfig.AddFiles->NumArgs() > 0) - { - auto fn = (*userConfig.AddFiles)[userConfig.AddFiles->NumArgs() - 1]; - bool isdir = false; - if (DirEntryExists(fn, &isdir) && isdir) + for (auto& file : *userConfig.AddFiles) { - // Insert the GRPs before this entry itself. - FString lastfn; - Files.Pop(lastfn); - D_AddDirectory(Files, fn); - Files.Push(lastfn); + D_AddFile(Files, file); + } + + // Finally, if the last entry in the chain is a directory, it's being considered the mod directory, and all GRPs inside need to be loaded, too. + if (userConfig.AddFiles->NumArgs() > 0) + { + auto fn = (*userConfig.AddFiles)[userConfig.AddFiles->NumArgs() - 1]; + bool isdir = false; + if (DirEntryExists(fn, &isdir) && isdir) + { + // Insert the GRPs before this entry itself. + FString lastfn; + Files.Pop(lastfn); + D_AddDirectory(Files, fn); + Files.Push(lastfn); + } } } const char* key; diff --git a/source/common/input/i_gui.cpp b/source/common/input/i_gui.cpp new file mode 100644 index 000000000..01a2362ca --- /dev/null +++ b/source/common/input/i_gui.cpp @@ -0,0 +1,87 @@ +/* +** i_gui.cpp +** +**--------------------------------------------------------------------------- +** Copyright 2008 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include + +#include + +#include "bitmap.h" +//#include "v_palette.h" +#include "textures.h" + +bool I_SetCursor(FTexture *cursorpic) +{ + static SDL_Cursor *cursor; + static SDL_Surface *cursorSurface; + + if (cursorpic != NULL) + { + auto src = cursorpic->GetBgraBitmap(nullptr); + // Must be no larger than 32x32. + if (src.GetWidth() > 32 || src.GetHeight() > 32) + { + return false; + } + + if (cursorSurface == NULL) + cursorSurface = SDL_CreateRGBSurface (0, 32, 32, 32, MAKEARGB(0,255,0,0), MAKEARGB(0,0,255,0), MAKEARGB(0,0,0,255), MAKEARGB(255,0,0,0)); + + SDL_LockSurface(cursorSurface); + uint8_t buffer[32*32*4]; + memset(buffer, 0, 32*32*4); + FBitmap bmp(buffer, 32*4, 32, 32); + bmp.Blit(0, 0, src); // expand to 32*32 + memcpy(cursorSurface->pixels, bmp.GetPixels(), 32*32*4); + SDL_UnlockSurface(cursorSurface); + + if (cursor) + SDL_FreeCursor (cursor); + cursor = SDL_CreateColorCursor (cursorSurface, 0, 0); + SDL_SetCursor (cursor); + } + else + { + if (cursor) + { + SDL_SetCursor (NULL); + SDL_FreeCursor (cursor); + cursor = NULL; + } + if (cursorSurface != NULL) + { + SDL_FreeSurface(cursorSurface); + cursorSurface = NULL; + } + } + return true; +} diff --git a/source/common/input/i_input.cpp b/source/common/input/i_input.cpp new file mode 100644 index 000000000..7b34c1b02 --- /dev/null +++ b/source/common/input/i_input.cpp @@ -0,0 +1,723 @@ +/* +** This code is partially original EDuke32 code, partially taken from ZDoom +** +** For the portions taken from ZDoom the following applies: +** +**--------------------------------------------------------------------------- +** Copyright 2005-2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include + +#include "m_argv.h" + +#include "c_buttons.h" +#include "d_event.h" +#include "d_gui.h" +#include "c_console.h" +#include "c_dispatch.h" +#include "c_cvars.h" +#include "keydef.h" +#include "utf8.h" +#include "menu/menu.h" + + +char grabmouse_low(char a); +void WindowMoved(int x, int y); +extern SDL_Window* sdl_window; + + +static uint8_t keytranslation[SDL_NUM_SCANCODES]; + +void buildkeytranslationtable(void) +{ + memset(keytranslation, 0, sizeof(keytranslation)); + +#define MAP(x,y) keytranslation[x] = y + MAP(SDL_SCANCODE_BACKSPACE, 0xe); + MAP(SDL_SCANCODE_TAB, 0xf); + MAP(SDL_SCANCODE_RETURN, 0x1c); + MAP(SDL_SCANCODE_PAUSE, 0x59); // 0x1d + 0x45 + 0x9d + 0xc5 + MAP(SDL_SCANCODE_ESCAPE, 0x1); + MAP(SDL_SCANCODE_SPACE, 0x39); + MAP(SDL_SCANCODE_COMMA, 0x33); + MAP(SDL_SCANCODE_NONUSBACKSLASH, 0x56); + MAP(SDL_SCANCODE_MINUS, 0xc); + MAP(SDL_SCANCODE_PERIOD, 0x34); + MAP(SDL_SCANCODE_SLASH, 0x35); + MAP(SDL_SCANCODE_0, 0xb); + MAP(SDL_SCANCODE_1, 0x2); + MAP(SDL_SCANCODE_2, 0x3); + MAP(SDL_SCANCODE_3, 0x4); + MAP(SDL_SCANCODE_4, 0x5); + MAP(SDL_SCANCODE_5, 0x6); + MAP(SDL_SCANCODE_6, 0x7); + MAP(SDL_SCANCODE_7, 0x8); + MAP(SDL_SCANCODE_8, 0x9); + MAP(SDL_SCANCODE_9, 0xa); + MAP(SDL_SCANCODE_SEMICOLON, 0x27); + MAP(SDL_SCANCODE_APOSTROPHE, 0x28); + MAP(SDL_SCANCODE_EQUALS, 0xd); + MAP(SDL_SCANCODE_LEFTBRACKET, 0x1a); + MAP(SDL_SCANCODE_BACKSLASH, 0x2b); + MAP(SDL_SCANCODE_RIGHTBRACKET, 0x1b); + MAP(SDL_SCANCODE_A, 0x1e); + MAP(SDL_SCANCODE_B, 0x30); + MAP(SDL_SCANCODE_C, 0x2e); + MAP(SDL_SCANCODE_D, 0x20); + MAP(SDL_SCANCODE_E, 0x12); + MAP(SDL_SCANCODE_F, 0x21); + MAP(SDL_SCANCODE_G, 0x22); + MAP(SDL_SCANCODE_H, 0x23); + MAP(SDL_SCANCODE_I, 0x17); + MAP(SDL_SCANCODE_J, 0x24); + MAP(SDL_SCANCODE_K, 0x25); + MAP(SDL_SCANCODE_L, 0x26); + MAP(SDL_SCANCODE_M, 0x32); + MAP(SDL_SCANCODE_N, 0x31); + MAP(SDL_SCANCODE_O, 0x18); + MAP(SDL_SCANCODE_P, 0x19); + MAP(SDL_SCANCODE_Q, 0x10); + MAP(SDL_SCANCODE_R, 0x13); + MAP(SDL_SCANCODE_S, 0x1f); + MAP(SDL_SCANCODE_T, 0x14); + MAP(SDL_SCANCODE_U, 0x16); + MAP(SDL_SCANCODE_V, 0x2f); + MAP(SDL_SCANCODE_W, 0x11); + MAP(SDL_SCANCODE_X, 0x2d); + MAP(SDL_SCANCODE_Y, 0x15); + MAP(SDL_SCANCODE_Z, 0x2c); + MAP(SDL_SCANCODE_DELETE, 0xd3); + MAP(SDL_SCANCODE_KP_0, 0x52); + MAP(SDL_SCANCODE_KP_1, 0x4f); + MAP(SDL_SCANCODE_KP_2, 0x50); + MAP(SDL_SCANCODE_KP_3, 0x51); + MAP(SDL_SCANCODE_KP_4, 0x4b); + MAP(SDL_SCANCODE_KP_5, 0x4c); + MAP(SDL_SCANCODE_KP_CLEAR, 0x4c); + MAP(SDL_SCANCODE_CLEAR, 0x4c); + MAP(SDL_SCANCODE_KP_6, 0x4d); + MAP(SDL_SCANCODE_KP_7, 0x47); + MAP(SDL_SCANCODE_KP_8, 0x48); + MAP(SDL_SCANCODE_KP_9, 0x49); + MAP(SDL_SCANCODE_KP_PERIOD, 0x53); + MAP(SDL_SCANCODE_KP_DIVIDE, 0xb5); + MAP(SDL_SCANCODE_KP_MULTIPLY, 0x37); + MAP(SDL_SCANCODE_KP_MINUS, 0x4a); + MAP(SDL_SCANCODE_KP_PLUS, 0x4e); + MAP(SDL_SCANCODE_KP_ENTER, 0x9c); + //MAP(SDL_SCANCODE_KP_EQUALS, ); + MAP(SDL_SCANCODE_UP, 0xc8); + MAP(SDL_SCANCODE_DOWN, 0xd0); + MAP(SDL_SCANCODE_RIGHT, 0xcd); + MAP(SDL_SCANCODE_LEFT, 0xcb); + MAP(SDL_SCANCODE_INSERT, 0xd2); + MAP(SDL_SCANCODE_HOME, 0xc7); + MAP(SDL_SCANCODE_END, 0xcf); + MAP(SDL_SCANCODE_PAGEUP, 0xc9); + MAP(SDL_SCANCODE_PAGEDOWN, 0xd1); + MAP(SDL_SCANCODE_F1, 0x3b); + MAP(SDL_SCANCODE_F2, 0x3c); + MAP(SDL_SCANCODE_F3, 0x3d); + MAP(SDL_SCANCODE_F4, 0x3e); + MAP(SDL_SCANCODE_F5, 0x3f); + MAP(SDL_SCANCODE_F6, 0x40); + MAP(SDL_SCANCODE_F7, 0x41); + MAP(SDL_SCANCODE_F8, 0x42); + MAP(SDL_SCANCODE_F9, 0x43); + MAP(SDL_SCANCODE_F10, 0x44); + MAP(SDL_SCANCODE_F11, 0x57); + MAP(SDL_SCANCODE_F12, 0x58); + MAP(SDL_SCANCODE_NUMLOCKCLEAR, 0x45); + MAP(SDL_SCANCODE_CAPSLOCK, 0x3a); + MAP(SDL_SCANCODE_SCROLLLOCK, 0x46); + MAP(SDL_SCANCODE_RSHIFT, 0x36); + MAP(SDL_SCANCODE_LSHIFT, 0x2a); + MAP(SDL_SCANCODE_RCTRL, 0x9d); + MAP(SDL_SCANCODE_LCTRL, 0x1d); + MAP(SDL_SCANCODE_RALT, 0xb8); + MAP(SDL_SCANCODE_LALT, 0x38); + MAP(SDL_SCANCODE_LGUI, 0xdb); // win l + MAP(SDL_SCANCODE_RGUI, 0xdc); // win r +// MAP(SDL_SCANCODE_PRINTSCREEN, -2); // 0xaa + 0xb7 + MAP(SDL_SCANCODE_SYSREQ, 0x54); // alt+printscr +// MAP(SDL_SCANCODE_PAUSE, 0xb7); // ctrl+pause + MAP(SDL_SCANCODE_MENU, 0xdd); // win menu? + MAP(SDL_SCANCODE_GRAVE, 0x29); // tilde +#undef MAP +} + + + +// +// initmouse() -- init mouse input +// +void mouseInit(void) +{ + mouseGrabInput(g_mouseEnabled = g_mouseLockedToWindow); // FIXME - SA +} + +// +// uninitmouse() -- uninit mouse input +// +void mouseUninit(void) +{ + mouseGrabInput(0); + g_mouseEnabled = 0; +} + + +// +// grabmouse_low() -- show/hide mouse cursor, lower level (doesn't check state). +// furthermore return 0 if successful. +// + +char grabmouse_low(char a) +{ + /* FIXME: Maybe it's better to make sure that grabmouse_low + is called only when a window is ready? */ + if (sdl_window) + SDL_SetWindowGrab(sdl_window, a ? SDL_TRUE : SDL_FALSE); + return SDL_SetRelativeMouseMode(a ? SDL_TRUE : SDL_FALSE); +} + +// +// grabmouse() -- show/hide mouse cursor +// +void mouseGrabInput(bool grab) +{ + if (appactive && g_mouseEnabled) + { + if ((grab != g_mouseGrabbed) && !grabmouse_low(grab)) + g_mouseGrabbed = grab; + } + else + g_mouseGrabbed = grab; + + inputState.MouseSetPos(0, 0); + SDL_ShowCursor(!grab ? SDL_ENABLE : SDL_DISABLE); + if (grab) GUICapture &= ~1; + else GUICapture |= 1; +} + + +// So this is how the engine handles text input? +// Argh. This is just gross. +int scancodetoasciihack(SDL_Event& ev) +{ + int sc = ev.key.keysym.scancode; + SDL_Keycode keyvalue = ev.key.keysym.sym; + int code = keytranslation[sc]; + // Modifiers that have to be held down to be effective + // (excludes KMOD_NUM, for example). + static const int MODIFIERS = + KMOD_LSHIFT | KMOD_RSHIFT | KMOD_LCTRL | KMOD_RCTRL | + KMOD_LALT | KMOD_RALT | KMOD_LGUI | KMOD_RGUI; + + // XXX: see osd.c, OSD_HandleChar(), there are more... + if ( + (sc == SDL_SCANCODE_RETURN || sc == SDL_SCANCODE_KP_ENTER || + sc == SDL_SCANCODE_ESCAPE || + sc == SDL_SCANCODE_BACKSPACE || + sc == SDL_SCANCODE_TAB || + (((ev.key.keysym.mod) & MODIFIERS) == KMOD_LCTRL && + (sc >= SDL_SCANCODE_A && sc <= SDL_SCANCODE_Z)))) + { + char keyvalue; + switch (sc) + { + case SDL_SCANCODE_RETURN: case SDL_SCANCODE_KP_ENTER: keyvalue = '\r'; break; + case SDL_SCANCODE_ESCAPE: keyvalue = 27; break; + case SDL_SCANCODE_BACKSPACE: keyvalue = '\b'; break; + case SDL_SCANCODE_TAB: keyvalue = '\t'; break; + default: keyvalue = sc - SDL_SCANCODE_A + 1; break; // Ctrl+A --> 1, etc. + } + } + else + { + /* + Necessary for Duke 3D's method of entering cheats to work without showing IMEs. + SDL_TEXTINPUT is preferable overall, but with bitmap fonts it has no advantage. + */ + // Note that this is not how text input is supposed to be handled! + + if ('a' <= keyvalue && keyvalue <= 'z') + { + if (!!(ev.key.keysym.mod & KMOD_SHIFT) ^ !!(ev.key.keysym.mod & KMOD_CAPS)) + keyvalue -= 'a' - 'A'; + } + else if (ev.key.keysym.mod & KMOD_SHIFT) + { + keyvalue = g_keyAsciiTableShift[code]; + } + else if (ev.key.keysym.mod & KMOD_NUM) // && !(ev.key.keysym.mod & KMOD_SHIFT) + { + switch (keyvalue) + { + case SDLK_KP_1: keyvalue = '1'; break; + case SDLK_KP_2: keyvalue = '2'; break; + case SDLK_KP_3: keyvalue = '3'; break; + case SDLK_KP_4: keyvalue = '4'; break; + case SDLK_KP_5: keyvalue = '5'; break; + case SDLK_KP_6: keyvalue = '6'; break; + case SDLK_KP_7: keyvalue = '7'; break; + case SDLK_KP_8: keyvalue = '8'; break; + case SDLK_KP_9: keyvalue = '9'; break; + case SDLK_KP_0: keyvalue = '0'; break; + case SDLK_KP_PERIOD: keyvalue = '.'; break; + case SDLK_KP_COMMA: keyvalue = ','; break; + } + } + + switch (keyvalue) + { + case SDLK_KP_DIVIDE: keyvalue = '/'; break; + case SDLK_KP_MULTIPLY: keyvalue = '*'; break; + case SDLK_KP_MINUS: keyvalue = '-'; break; + case SDLK_KP_PLUS: keyvalue = '+'; break; + } + } + if (keyvalue >= 0x80) keyvalue = 0; // Sadly ASCII only... + return keyvalue; +} + +static void PostMouseMove(int x, int y) +{ + static int lastx = 0, lasty = 0; + event_t ev = { 0,0,0,0,0,0,0 }; + + ev.x = x; + ev.y = y; + lastx = x; + lasty = y; + if (ev.x | ev.y) + { + ev.type = EV_Mouse; + D_PostEvent(&ev); + } +} + +CVAR(Bool, m_noprescale, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) + +static void MouseRead() +{ + int x, y; + +#if 0 + if (NativeMouse) + { + return; + } +#endif + + SDL_GetRelativeMouseState(&x, &y); + if (!m_noprescale) + { + x *= 3; + y *= 2; + } + if (x | y) + { + PostMouseMove(x, -y); + } +} + +int32_t handleevents_pollsdl(void) +{ + int32_t code, rv = 0, j; + SDL_Event ev; + event_t evt; + + while (SDL_PollEvent(&ev)) + { + switch (ev.type) + { + case SDL_TEXTINPUT: + { + j = 0; + const uint8_t* text = (uint8_t*)ev.text.text; + while ((j = GetCharFromString(text))) + { + code = ev.text.text[j]; + // Fixme: Send an EV_GUI_Event instead and properly deal with Unicode. + if ((GUICapture & 1) && menuactive != MENU_WaitKey) + { + evt = { EV_GUI_Event, EV_GUI_Char, int16_t(j), !!(SDL_GetModState() & KMOD_ALT) }; + D_PostEvent(&evt); + } + } + break; + } + + case SDL_KEYDOWN: + case SDL_KEYUP: + { + if ((GUICapture & 1) && menuactive != MENU_WaitKey) + { + evt = {}; + evt.type = EV_GUI_Event; + evt.subtype = ev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp; + SDL_Keymod kmod = SDL_GetModState(); + evt.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | + ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | + ((kmod & KMOD_ALT) ? GKM_ALT : 0); + + if (evt.subtype == EV_GUI_KeyDown && ev.key.repeat) + { + evt.subtype = EV_GUI_KeyRepeat; + } + + switch (ev.key.keysym.sym) + { + case SDLK_KP_ENTER: evt.data1 = GK_RETURN; break; + case SDLK_PAGEUP: evt.data1 = GK_PGUP; break; + case SDLK_PAGEDOWN: evt.data1 = GK_PGDN; break; + case SDLK_END: evt.data1 = GK_END; break; + case SDLK_HOME: evt.data1 = GK_HOME; break; + case SDLK_LEFT: evt.data1 = GK_LEFT; break; + case SDLK_RIGHT: evt.data1 = GK_RIGHT; break; + case SDLK_UP: evt.data1 = GK_UP; break; + case SDLK_DOWN: evt.data1 = GK_DOWN; break; + case SDLK_DELETE: evt.data1 = GK_DEL; break; + case SDLK_ESCAPE: evt.data1 = GK_ESCAPE; break; + case SDLK_F1: evt.data1 = GK_F1; break; + case SDLK_F2: evt.data1 = GK_F2; break; + case SDLK_F3: evt.data1 = GK_F3; break; + case SDLK_F4: evt.data1 = GK_F4; break; + case SDLK_F5: evt.data1 = GK_F5; break; + case SDLK_F6: evt.data1 = GK_F6; break; + case SDLK_F7: evt.data1 = GK_F7; break; + case SDLK_F8: evt.data1 = GK_F8; break; + case SDLK_F9: evt.data1 = GK_F9; break; + case SDLK_F10: evt.data1 = GK_F10; break; + case SDLK_F11: evt.data1 = GK_F11; break; + case SDLK_F12: evt.data1 = GK_F12; break; + default: + if (ev.key.keysym.sym < 256) + { + evt.data1 = ev.key.keysym.sym; + } + break; + } + if (evt.data1 < 128) + { + evt.data1 = toupper(evt.data1); + D_PostEvent(&evt); + } + } + else + { + auto const& sc = ev.key.keysym.scancode; + code = keytranslation[sc]; + + // The pause key generates a release event right after + // the pressing one. As a result, it gets unseen + // by the game most of the time. + if (code == 0x59 && ev.type == SDL_KEYUP) // pause + break; + + int keyvalue = ev.type == SDL_KEYDOWN ? scancodetoasciihack(ev) : 0; + event_t evt = { (uint8_t)(ev.type == SDL_KEYUP ? EV_KeyUp : EV_KeyDown), 0, (int16_t)code, (int16_t)keyvalue }; + D_PostEvent(&evt); + } + + break; + } + + case SDL_MOUSEWHEEL: + if (GUICapture) + { + evt.type = EV_GUI_Event; + + if (ev.wheel.y == 0) + evt.subtype = ev.wheel.x > 0 ? EV_GUI_WheelRight : EV_GUI_WheelLeft; + else + evt.subtype = ev.wheel.y > 0 ? EV_GUI_WheelUp : EV_GUI_WheelDown; + + SDL_Keymod kmod = SDL_GetModState(); + evt.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | + ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | + ((kmod & KMOD_ALT) ? GKM_ALT : 0); + + D_PostEvent(&evt); + } + else + { + // This never sends keyup events. They must be delayed for this to work with game buttons. + if (ev.wheel.y > 0) + { + evt = { EV_KeyDown, 0, (int16_t)KEY_MWHEELUP }; + D_PostEvent(&evt); + } + if (ev.wheel.y < 0) + { + evt = { EV_KeyDown, 0, (int16_t)KEY_MWHEELDOWN }; + D_PostEvent(&evt); + } + if (ev.wheel.x > 0) + { + evt = { EV_KeyDown, 0, (int16_t)KEY_MWHEELRIGHT }; + D_PostEvent(&evt); + } + if (ev.wheel.y < 0) + { + evt = { EV_KeyDown, 0, (int16_t)KEY_MWHEELLEFT }; + D_PostEvent(&evt); + } + } + break; + + case SDL_WINDOWEVENT: + switch (ev.window.event) + { + case SDL_WINDOWEVENT_FOCUS_GAINED: + case SDL_WINDOWEVENT_FOCUS_LOST: + appactive = (ev.window.event == SDL_WINDOWEVENT_FOCUS_GAINED); + if (g_mouseGrabbed && g_mouseEnabled) + grabmouse_low(appactive); + break; + + case SDL_WINDOWEVENT_MOVED: + { + WindowMoved(ev.window.data1, ev.window.data2); + break; + } + case SDL_WINDOWEVENT_ENTER: + g_mouseInsideWindow = 1; + break; + case SDL_WINDOWEVENT_LEAVE: + g_mouseInsideWindow = 0; + break; + } + + break; + + case SDL_MOUSEMOTION: + //case SDL_JOYBALLMOTION: + { + // The menus need this, even in non GUI-capture mode + event_t event; + event.data1 = ev.motion.x; + event.data2 = ev.motion.y; + + //screen->ScaleCoordsFromWindow(event.data1, event.data2); + + event.type = EV_GUI_Event; + event.subtype = EV_GUI_MouseMove; + + SDL_Keymod kmod = SDL_GetModState(); + event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | + ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | + ((kmod & KMOD_ALT) ? GKM_ALT : 0); + + D_PostEvent(&event); + break; + } + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + + if (!GUICapture) + { + evt.type = ev.type == SDL_MOUSEBUTTONDOWN ? EV_KeyDown : EV_KeyUp; + + switch (ev.button.button) + { + case SDL_BUTTON_LEFT: evt.data1 = KEY_MOUSE1; break; + case SDL_BUTTON_MIDDLE: evt.data1 = KEY_MOUSE3; break; + case SDL_BUTTON_RIGHT: evt.data1 = KEY_MOUSE2; break; + case SDL_BUTTON_X1: evt.data1 = KEY_MOUSE4; break; + case SDL_BUTTON_X2: evt.data1 = KEY_MOUSE5; break; + case 6: evt.data1 = KEY_MOUSE6; break; + case 7: evt.data1 = KEY_MOUSE7; break; + case 8: evt.data1 = KEY_MOUSE8; break; + //default: printf("SDL mouse button %s %d\n", sev.type == SDL_MOUSEBUTTONDOWN ? "down" : "up", sev.button.button); break; + } + + if (evt.data1 != 0) + { + D_PostEvent(&evt); + } + } + else if ((ev.button.button >= SDL_BUTTON_LEFT && ev.button.button <= SDL_BUTTON_X2)) + { + int x, y; + SDL_GetMouseState(&x, &y); + + evt.type = EV_GUI_Event; + evt.data1 = x; + evt.data2 = y; + + //screen->ScaleCoordsFromWindow(event.data1, event.data2); + + if (ev.type == SDL_MOUSEBUTTONDOWN) + { + switch (ev.button.button) + { + case SDL_BUTTON_LEFT: evt.subtype = EV_GUI_LButtonDown; break; + case SDL_BUTTON_MIDDLE: evt.subtype = EV_GUI_MButtonDown; break; + case SDL_BUTTON_RIGHT: evt.subtype = EV_GUI_RButtonDown; break; + case SDL_BUTTON_X1: evt.subtype = EV_GUI_BackButtonDown; break; + case SDL_BUTTON_X2: evt.subtype = EV_GUI_FwdButtonDown; break; + default: assert(false); evt.subtype = EV_GUI_None; break; + } + } + else + { + switch (ev.button.button) + { + case SDL_BUTTON_LEFT: evt.subtype = EV_GUI_LButtonUp; break; + case SDL_BUTTON_MIDDLE: evt.subtype = EV_GUI_MButtonUp; break; + case SDL_BUTTON_RIGHT: evt.subtype = EV_GUI_RButtonUp; break; + case SDL_BUTTON_X1: evt.subtype = EV_GUI_BackButtonUp; break; + case SDL_BUTTON_X2: evt.subtype = EV_GUI_FwdButtonUp; break; + default: assert(false); evt.subtype = EV_GUI_None; break; + } + } + + SDL_Keymod kmod = SDL_GetModState(); + evt.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) | + ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) | + ((kmod & KMOD_ALT) ? GKM_ALT : 0); + + D_PostEvent(&evt); + } + break; + + case SDL_JOYHATMOTION: + { + int32_t hatvals[16] = { + -1, // centre + 0, // up 1 + 9000, // right 2 + 4500, // up+right 3 + 18000, // down 4 + -1, // down+up!! 5 + 13500, // down+right 6 + -1, // down+right+up!! 7 + 27000, // left 8 + 27500, // left+up 9 + -1, // left+right!! 10 + -1, // left+right+up!! 11 + 22500, // left+down 12 + -1, // left+down+up!! 13 + -1, // left+down+right!! 14 + -1, // left+down+right+up!! 15 + }; + if (appactive && ev.jhat.hat < joystick.numHats) + joystick.pHat[ev.jhat.hat] = hatvals[ev.jhat.value & 15]; + break; + } + + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: +#if 0 // SDL_MAJOR_VERSION >= 2 + if (joystick.isGameController) + break; + fallthrough__; + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: +#endif + if (!GUICapture) + { + evt.type = ev.type == SDL_JOYBUTTONDOWN ? EV_KeyDown : EV_KeyUp; + evt.data1 = KEY_FIRSTJOYBUTTON + ev.jbutton.button; + if (evt.data1 != 0) + D_PostEvent(&evt); + } + break; + + case SDL_QUIT: + throw ExitEvent(0); // completely bypass the hackery in the games to block Alt-F4. + return -1; + + default: + break; + } + } + MouseRead(); + + return rv; +} + +int32_t handleevents(void) +{ + int32_t rv; + + if (inputchecked && g_mouseEnabled) + { + // This is a horrible crutch + if (inputState.mouseReadButtons() & WHEELUP_MOUSE) + { + event_t ev = { EV_KeyUp, 0, (int16_t)KEY_MWHEELUP }; + D_PostEvent(&ev); + } + if (inputState.mouseReadButtons() & WHEELDOWN_MOUSE) + { + event_t ev = { EV_KeyUp, 0, (int16_t)KEY_MWHEELDOWN }; + D_PostEvent(&ev); + } + if (inputState.mouseReadButtons() & WHEELLEFT_MOUSE) + { + event_t ev = { EV_KeyUp, 0, (int16_t)KEY_MWHEELLEFT }; + D_PostEvent(&ev); + } + if (inputState.mouseReadButtons() & WHEELRIGHT_MOUSE) + { + event_t ev = { EV_KeyUp, 0, (int16_t)KEY_MWHEELRIGHT }; + D_PostEvent(&ev); + } + } + + rv = handleevents_pollsdl(); + + inputchecked = 0; + timerUpdateClock(); + //I_ProcessJoysticks(); + return rv; +} + + +int32_t handleevents_peekkeys(void) +{ + SDL_PumpEvents(); + + return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYDOWN); +} + +void I_SetMouseCapture() +{ + // Clear out any mouse movement. + SDL_CaptureMouse(SDL_TRUE); +} + +void I_ReleaseMouseCapture() +{ + SDL_CaptureMouse(SDL_FALSE); +} diff --git a/source/common/input/i_joystick.cpp b/source/common/input/i_joystick.cpp new file mode 100644 index 000000000..695a44686 --- /dev/null +++ b/source/common/input/i_joystick.cpp @@ -0,0 +1,342 @@ +/* +** i_joystick.cpp +** +**--------------------------------------------------------------------------- +** Copyright 2005-2016 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ +#include + +#include "basics.h" +#include "templates.h" +#include "m_joy.h" +#include "keydef.h" + +// Very small deadzone so that floating point magic doesn't happen +#define MIN_DEADZONE 0.000001f + +class SDLInputJoystick: public IJoystickConfig +{ +public: + SDLInputJoystick(int DeviceIndex) : DeviceIndex(DeviceIndex), Multiplier(1.0f) + { + Device = SDL_JoystickOpen(DeviceIndex); + if(Device != NULL) + { + NumAxes = SDL_JoystickNumAxes(Device); + NumHats = SDL_JoystickNumHats(Device); + + SetDefaultConfig(); + } + } + ~SDLInputJoystick() + { + if(Device != NULL) + M_SaveJoystickConfig(this); + SDL_JoystickClose(Device); + } + + bool IsValid() const + { + return Device != NULL; + } + + FString GetName() + { + return SDL_JoystickName(Device); + } + float GetSensitivity() + { + return Multiplier; + } + void SetSensitivity(float scale) + { + Multiplier = scale; + } + + int GetNumAxes() + { + return NumAxes + NumHats*2; + } + float GetAxisDeadZone(int axis) + { + return Axes[axis].DeadZone; + } + EJoyAxis GetAxisMap(int axis) + { + return Axes[axis].GameAxis; + } + const char *GetAxisName(int axis) + { + return Axes[axis].Name.GetChars(); + } + float GetAxisScale(int axis) + { + return Axes[axis].Multiplier; + } + + void SetAxisDeadZone(int axis, float zone) + { + Axes[axis].DeadZone = clamp(zone, MIN_DEADZONE, 1.f); + } + void SetAxisMap(int axis, EJoyAxis gameaxis) + { + Axes[axis].GameAxis = gameaxis; + } + void SetAxisScale(int axis, float scale) + { + Axes[axis].Multiplier = scale; + } + + // Used by the saver to not save properties that are at their defaults. + bool IsSensitivityDefault() + { + return Multiplier == 1.0f; + } + bool IsAxisDeadZoneDefault(int axis) + { + return Axes[axis].DeadZone <= MIN_DEADZONE; + } + bool IsAxisMapDefault(int axis) + { + if(axis >= 5) + return Axes[axis].GameAxis == JOYAXIS_None; + return Axes[axis].GameAxis == DefaultAxes[axis]; + } + bool IsAxisScaleDefault(int axis) + { + return Axes[axis].Multiplier == 1.0f; + } + + void SetDefaultConfig() + { + for(int i = 0;i < GetNumAxes();i++) + { + AxisInfo info; + if(i < NumAxes) + info.Name.Format("Axis %d", i+1); + else + info.Name.Format("Hat %d (%c)", (i-NumAxes)/2 + 1, (i-NumAxes)%2 == 0 ? 'x' : 'y'); + info.DeadZone = MIN_DEADZONE; + info.Multiplier = 1.0f; + info.Value = 0.0; + info.ButtonValue = 0; + if(i >= 5) + info.GameAxis = JOYAXIS_None; + else + info.GameAxis = DefaultAxes[i]; + Axes.Push(info); + } + } + FString GetIdentifier() + { + char id[16]; + snprintf(id, countof(id), "JS:%d", DeviceIndex); + return id; + } + + void AddAxes(float axes[NUM_JOYAXIS]) + { + // Add to game axes. + for (int i = 0; i < GetNumAxes(); ++i) + { + if(Axes[i].GameAxis != JOYAXIS_None) + axes[Axes[i].GameAxis] -= float(Axes[i].Value * Multiplier * Axes[i].Multiplier); + } + } + + void ProcessInput() + { + uint8_t buttonstate; + + for (int i = 0; i < NumAxes; ++i) + { + buttonstate = 0; + + Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32767.0; + Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate); + + // Map button to axis + // X and Y are handled differently so if we have 2 or more axes then we'll use that code instead. + if (NumAxes == 1 || (i >= 2 && i < NUM_JOYAXISBUTTONS)) + { + Joy_GenerateButtonEvents(Axes[i].ButtonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2); + Axes[i].ButtonValue = buttonstate; + } + } + + if(NumAxes > 1) + { + buttonstate = Joy_XYAxesToButtons(Axes[0].Value, Axes[1].Value); + Joy_GenerateButtonEvents(Axes[0].ButtonValue, buttonstate, 4, KEY_JOYAXIS1PLUS); + Axes[0].ButtonValue = buttonstate; + } + + // Map POV hats to buttons and axes. Why axes? Well apparently I have + // a gamepad where the left control stick is a POV hat (instead of the + // d-pad like you would expect, no that's pressure sensitive). Also + // KDE's joystick dialog maps them to axes as well. + for (int i = 0; i < NumHats; ++i) + { + AxisInfo &x = Axes[NumAxes + i*2]; + AxisInfo &y = Axes[NumAxes + i*2 + 1]; + + buttonstate = SDL_JoystickGetHat(Device, i); + + // If we're going to assume that we can pass SDL's value into + // Joy_GenerateButtonEvents then we might as well assume the format here. + if(buttonstate & 0x1) // Up + y.Value = -1.0; + else if(buttonstate & 0x4) // Down + y.Value = 1.0; + else + y.Value = 0.0; + if(buttonstate & 0x2) // Left + x.Value = 1.0; + else if(buttonstate & 0x8) // Right + x.Value = -1.0; + else + x.Value = 0.0; + + if(i < 4) + { + Joy_GenerateButtonEvents(x.ButtonValue, buttonstate, 4, KEY_JOYPOV1_UP + i*4); + x.ButtonValue = buttonstate; + } + } + } + +protected: + struct AxisInfo + { + FString Name; + float DeadZone; + float Multiplier; + EJoyAxis GameAxis; + double Value; + uint8_t ButtonValue; + }; + static const EJoyAxis DefaultAxes[5]; + + int DeviceIndex; + SDL_Joystick *Device; + + float Multiplier; + TArray Axes; + int NumAxes; + int NumHats; +}; +const EJoyAxis SDLInputJoystick::DefaultAxes[5] = {JOYAXIS_Side, JOYAXIS_Forward, JOYAXIS_Pitch, JOYAXIS_Yaw, JOYAXIS_Up}; + +class SDLInputJoystickManager +{ +public: + SDLInputJoystickManager() + { + for(int i = 0;i < SDL_NumJoysticks();i++) + { + SDLInputJoystick *device = new SDLInputJoystick(i); + if(device->IsValid()) + Joysticks.Push(device); + else + delete device; + } + } + ~SDLInputJoystickManager() + { + for(unsigned int i = 0;i < Joysticks.Size();i++) + delete Joysticks[i]; + } + + void AddAxes(float axes[NUM_JOYAXIS]) + { + for(unsigned int i = 0;i < Joysticks.Size();i++) + Joysticks[i]->AddAxes(axes); + } + void GetDevices(TArray &sticks) + { + for(unsigned int i = 0;i < Joysticks.Size();i++) + { + M_LoadJoystickConfig(Joysticks[i]); + sticks.Push(Joysticks[i]); + } + } + + void ProcessInput() const + { + for(unsigned int i = 0;i < Joysticks.Size();++i) + Joysticks[i]->ProcessInput(); + } +protected: + TArray Joysticks; +}; +static SDLInputJoystickManager *JoystickManager; + +void I_StartupJoysticks() +{ + if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0) + JoystickManager = new SDLInputJoystickManager(); +} +void I_ShutdownInput() +{ + if(JoystickManager) + { + delete JoystickManager; + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + } +} + +void I_GetJoysticks(TArray &sticks) +{ + sticks.Clear(); + + JoystickManager->GetDevices(sticks); +} + +void I_GetAxes(float axes[NUM_JOYAXIS]) +{ + for (int i = 0; i < NUM_JOYAXIS; ++i) + { + axes[i] = 0; + } + if (use_joystick) + { + JoystickManager->AddAxes(axes); + } +} + +void I_ProcessJoysticks() +{ + if (use_joystick && JoystickManager) + JoystickManager->ProcessInput(); +} + +IJoystickConfig *I_UpdateDeviceList() +{ + return NULL; +} diff --git a/source/mact/src/input.cpp b/source/common/input/input.cpp similarity index 84% rename from source/mact/src/input.cpp rename to source/common/input/input.cpp index 3687637a7..0b7f25939 100644 --- a/source/mact/src/input.cpp +++ b/source/common/input/input.cpp @@ -21,10 +21,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //------------------------------------------------------------------------- #include "gamecontrol.h" -#include "keyboard.h" -#include "mouse.h" -#include "joystick.h" -#include "control.h" #include "input.h" #include "inputstate.h" @@ -41,14 +37,15 @@ int32_t I_CheckAllInput(void) return inputState.keyBufferWaiting() || inputState.MouseGetButtons() - || JOYSTICK_GetButtons(); + //|| JOYSTICK_GetButtons() + ; } void I_ClearAllInput(void) { inputState.keyFlushChars(); inputState.ClearKeysDown(); inputState.MouseClearAllButtonss(); - JOYSTICK_ClearAllButtons(); + //JOYSTICK_ClearAllButtons(); buttonMap.ResetButtonStates(); } @@ -59,7 +56,7 @@ int32_t I_TextSubmit(void) inputState.GetKeyStatus(sc_Enter) || inputState.GetKeyStatus(sc_kpad_Enter) || mouseInactiveConditional(inputState.MouseGetButtons()&LEFT_MOUSE) - || (JOYSTICK_GetGameControllerButtons()&(1< +#include "vectors.h" +#include "m_joy.h" +#include "gameconfigfile.h" +#include "d_event.h" + +// MACROS ------------------------------------------------------------------ + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +#if 0 +EXTERN_CVAR(Bool, joy_ps2raw) +EXTERN_CVAR(Bool, joy_dinput) +EXTERN_CVAR(Bool, joy_xinput) +#endif + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +CUSTOM_CVAR(Bool, use_joystick, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) +{ +#if 0//def _WIN32 + joy_ps2raw.Callback(); + joy_dinput.Callback(); + joy_xinput.Callback(); +#endif +} + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// Bits 0 is X+, 1 is X-, 2 is Y+, and 3 is Y-. +static uint8_t JoyAngleButtons[8] = { 1, 1+4, 4, 2+4, 2, 2+8, 8, 1+8 }; + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// IJoystickConfig - Virtual Destructor +// +//========================================================================== + +IJoystickConfig::~IJoystickConfig() +{ +} + +//========================================================================== +// +// M_SetJoystickConfigSection +// +// Sets up the config for reading or writing this controller's axis config. +// +//========================================================================== + +static bool M_SetJoystickConfigSection(IJoystickConfig *joy, bool create) +{ + FString id = "Joy:"; + id += joy->GetIdentifier(); + return GameConfig->SetSection(id, create); +} + +//========================================================================== +// +// M_LoadJoystickConfig +// +//========================================================================== + +bool M_LoadJoystickConfig(IJoystickConfig *joy) +{ + char key[32]; + const char *value; + int axislen; + int numaxes; + + joy->SetDefaultConfig(); + if (!M_SetJoystickConfigSection(joy, false)) + { + return false; + } + value = GameConfig->GetValueForKey("Sensitivity"); + if (value != NULL) + { + joy->SetSensitivity((float)atof(value)); + } + numaxes = joy->GetNumAxes(); + for (int i = 0; i < numaxes; ++i) + { + axislen = snprintf(key, countof(key), "Axis%u", i); + + snprintf(key + axislen, countof(key) - axislen, "deadzone"); + value = GameConfig->GetValueForKey(key); + if (value != NULL) + { + joy->SetAxisDeadZone(i, (float)atof(value)); + } + + snprintf(key + axislen, countof(key) - axislen, "scale"); + value = GameConfig->GetValueForKey(key); + if (value != NULL) + { + joy->SetAxisScale(i, (float)atof(value)); + } + + snprintf(key + axislen, countof(key) - axislen, "map"); + value = GameConfig->GetValueForKey(key); + if (value != NULL) + { + EJoyAxis gameaxis = (EJoyAxis)atoi(value); + if (gameaxis < JOYAXIS_None || gameaxis >= NUM_JOYAXIS) + { + gameaxis = JOYAXIS_None; + } + joy->SetAxisMap(i, gameaxis); + } + } + return true; +} + +//========================================================================== +// +// M_SaveJoystickConfig +// +// Only saves settings that are not at their defaults. +// +//========================================================================== + +void M_SaveJoystickConfig(IJoystickConfig *joy) +{ + char key[32], value[32]; + int axislen, numaxes; + + if (M_SetJoystickConfigSection(joy, true)) + { + GameConfig->ClearCurrentSection(); + if (!joy->IsSensitivityDefault()) + { + snprintf(value, countof(value), "%g", joy->GetSensitivity()); + GameConfig->SetValueForKey("Sensitivity", value); + } + numaxes = joy->GetNumAxes(); + for (int i = 0; i < numaxes; ++i) + { + axislen = snprintf(key, countof(key), "Axis%u", i); + + if (!joy->IsAxisDeadZoneDefault(i)) + { + snprintf(key + axislen, countof(key) - axislen, "deadzone"); + snprintf(value, countof(value), "%g", joy->GetAxisDeadZone(i)); + GameConfig->SetValueForKey(key, value); + } + if (!joy->IsAxisScaleDefault(i)) + { + snprintf(key + axislen, countof(key) - axislen, "scale"); + snprintf(value, countof(value), "%g", joy->GetAxisScale(i)); + GameConfig->SetValueForKey(key, value); + } + if (!joy->IsAxisMapDefault(i)) + { + snprintf(key + axislen, countof(key) - axislen, "map"); + snprintf(value, countof(value), "%d", joy->GetAxisMap(i)); + GameConfig->SetValueForKey(key, value); + } + } + // If the joystick is entirely at its defaults, delete this section + // so that we don't write out a lone section header. + if (GameConfig->SectionIsEmpty()) + { + GameConfig->DeleteCurrentSection(); + } + } +} + + +//=========================================================================== +// +// Joy_RemoveDeadZone +// +//=========================================================================== + +double Joy_RemoveDeadZone(double axisval, double deadzone, uint8_t *buttons) +{ + uint8_t butt; + + // Cancel out deadzone. + if (fabs(axisval) < deadzone) + { + axisval = 0; + butt = 0; + } + // Make the dead zone the new 0. + else if (axisval < 0) + { + axisval = (axisval + deadzone) / (1.0 - deadzone); + butt = 2; // button minus + } + else + { + axisval = (axisval - deadzone) / (1.0 - deadzone); + butt = 1; // button plus + } + if (buttons != NULL) + { + *buttons = butt; + } + return axisval; +} + +//=========================================================================== +// +// Joy_XYAxesToButtons +// +// Given two axes, returns a button set for them. They should have already +// been sent through Joy_RemoveDeadZone. For axes that share the same +// physical stick, the angle the stick forms should determine whether or +// not the four component buttons are present. Going by deadzone alone gives +// you huge areas where you have to buttons pressed and thin strips where +// you only have one button pressed. For DirectInput gamepads, there is +// not much standard for how the right stick is presented, so we can only +// do this for the left stick for those, since X and Y axes are pretty +// standard. For XInput and Raw PS2 controllers, both sticks are processed +// through here. +// +//=========================================================================== + +int Joy_XYAxesToButtons(double x, double y) +{ + if (x == 0 && y == 0) + { + return 0; + } + double rad = atan2(y, x); + if (rad < 0) + { + rad += 2*pi::pi(); + } + // The circle is divided into eight segments for corresponding + // button combinations. Each segment is pi/4 radians wide. We offset + // by half this so that the segments are centered around the ideal lines + // their buttons represent instead of being right on the lines. + rad += pi::pi()/8; // Offset + rad *= 4/pi::pi(); // Convert range from [0,2pi) to [0,8) + return JoyAngleButtons[int(rad) & 7]; +} + +//=========================================================================== +// +// Joy_GenerateButtonEvents +// +// Provided two bitmasks for a set of buttons, generates events to reflect +// any changes from the old to new set, where base is the key for bit 0, +// base+1 is the key for bit 1, etc. +// +//=========================================================================== + +void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base) +{ + int changed = oldbuttons ^ newbuttons; + if (changed != 0) + { + event_t ev = { 0, 0, 0, 0, 0, 0, 0 }; + int mask = 1; + for (int j = 0; j < numbuttons; mask <<= 1, ++j) + { + if (changed & mask) + { + ev.data1 = base + j; + ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp; + D_PostEvent(&ev); + } + } + } +} + +void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys) +{ + int changed = oldbuttons ^ newbuttons; + if (changed != 0) + { + event_t ev = { 0, 0, 0, 0, 0, 0, 0 }; + int mask = 1; + for (int j = 0; j < numbuttons; mask <<= 1, ++j) + { + if (changed & mask) + { + ev.data1 = keys[j]; + ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp; + D_PostEvent(&ev); + } + } + } +} diff --git a/source/common/input/m_joy.h b/source/common/input/m_joy.h new file mode 100644 index 000000000..90cea3e14 --- /dev/null +++ b/source/common/input/m_joy.h @@ -0,0 +1,65 @@ +#ifndef M_JOY_H +#define M_JOY_H + +#include +#include "tarray.h" +#include "c_cvars.h" + +enum EJoyAxis +{ + JOYAXIS_None = -1, + JOYAXIS_Yaw, + JOYAXIS_Pitch, + JOYAXIS_Forward, + JOYAXIS_Side, + JOYAXIS_Up, +// JOYAXIS_Roll, // Ha ha. No roll for you. + NUM_JOYAXIS, +}; + +// Generic configuration interface for a controller. +struct IJoystickConfig +{ + virtual ~IJoystickConfig() = 0; + + virtual FString GetName() = 0; + virtual float GetSensitivity() = 0; + virtual void SetSensitivity(float scale) = 0; + + virtual int GetNumAxes() = 0; + virtual float GetAxisDeadZone(int axis) = 0; + virtual EJoyAxis GetAxisMap(int axis) = 0; + virtual const char *GetAxisName(int axis) = 0; + virtual float GetAxisScale(int axis) = 0; + + virtual void SetAxisDeadZone(int axis, float zone) = 0; + virtual void SetAxisMap(int axis, EJoyAxis gameaxis) = 0; + virtual void SetAxisScale(int axis, float scale) = 0; + + // Used by the saver to not save properties that are at their defaults. + virtual bool IsSensitivityDefault() = 0; + virtual bool IsAxisDeadZoneDefault(int axis) = 0; + virtual bool IsAxisMapDefault(int axis) = 0; + virtual bool IsAxisScaleDefault(int axis) = 0; + + virtual void SetDefaultConfig() = 0; + virtual FString GetIdentifier() = 0; +}; + +EXTERN_CVAR(Bool, use_joystick); + +bool M_LoadJoystickConfig(IJoystickConfig *joy); +void M_SaveJoystickConfig(IJoystickConfig *joy); + +void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base); +void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys); +int Joy_XYAxesToButtons(double x, double y); +double Joy_RemoveDeadZone(double axisval, double deadzone, uint8_t *buttons); + +// These ought to be provided by a system-specific i_input.cpp. +void I_GetAxes(float axes[NUM_JOYAXIS]); +void I_GetJoysticks(TArray &sticks); +IJoystickConfig *I_UpdateDeviceList(); +extern void UpdateJoystickMenu(IJoystickConfig *); + +#endif diff --git a/source/common/inputstate.cpp b/source/common/inputstate.cpp index f5a3e6ced..ef7c45452 100644 --- a/source/common/inputstate.cpp +++ b/source/common/inputstate.cpp @@ -83,6 +83,8 @@ void InputState::AddEvent(const event_t *ev) case KEY_MOUSE4 : mouseSetBit(THUMB_MOUSE, ev->type == EV_KeyDown); break; case KEY_MWHEELUP: mouseSetBit(WHEELUP_MOUSE, ev->type == EV_KeyDown); break; case KEY_MWHEELDOWN: mouseSetBit(WHEELDOWN_MOUSE, ev->type == EV_KeyDown); break; + case KEY_MWHEELLEFT: mouseSetBit(WHEELLEFT_MOUSE, ev->type == EV_KeyDown); break; + case KEY_MWHEELRIGHT: mouseSetBit(WHEELRIGHT_MOUSE, ev->type == EV_KeyDown); break; case KEY_MOUSE5: mouseSetBit(THUMB2_MOUSE, ev->type == EV_KeyDown); break; default: break; } diff --git a/source/common/inputstate.h b/source/common/inputstate.h index 4639e2a5e..47d58f2cf 100644 --- a/source/common/inputstate.h +++ b/source/common/inputstate.h @@ -7,6 +7,8 @@ #include "c_buttons.h" #include "d_event.h" #include "osd.h" +#include "m_joy.h" +#include "gamecvars.h" extern char appactive; @@ -21,8 +23,6 @@ enum MAXMOUSEBUTTONS = 10, }; -extern bool CONTROL_BindsEnabled; - extern bool g_mouseGrabbed; extern bool g_mouseEnabled; extern bool g_mouseInsideWindow; @@ -39,6 +39,8 @@ enum EMouseBits WHEELUP_MOUSE = 16, WHEELDOWN_MOUSE= 32, THUMB2_MOUSE = 64, + WHEELLEFT_MOUSE = 128, + WHEELRIGHT_MOUSE = 256, }; enum @@ -135,8 +137,6 @@ public: void SetBindsEnabled(bool on) { - // This just forwards the setting - CONTROL_BindsEnabled = on; } bool keyBufferWaiting() @@ -296,6 +296,12 @@ public: { g_mouseAbs = { x, y }; } + + bool gamePadActive() + { + // fixme: This needs to be tracked. + return false; + } int32_t MouseGetButtons(void) { return mouseReadButtons(); } inline void MouseClearButton(int32_t b) { g_mouseBits &= ~b; } inline void MouseClearAllButtonss(void) { g_mouseBits = 0; } @@ -311,7 +317,28 @@ public: }; - - extern InputState inputState; +inline void CONTROL_GetInput(ControlInfo* info) +{ + memset(info, 0, sizeof(ControlInfo)); + + if (in_mouse) + inputState.GetMouseDelta(info); + + if (in_joystick) + { + // Handle joysticks/game controllers. + float joyaxes[NUM_JOYAXIS]; + + I_GetAxes(joyaxes); + + info->dyaw += joyaxes[JOYAXIS_Yaw]; + info->dx += joyaxes[JOYAXIS_Side]; + info->dz += joyaxes[JOYAXIS_Forward]; + info->dpitch += joyaxes[JOYAXIS_Pitch]; + } +} + + + diff --git a/source/common/menu/joystickmenu.cpp b/source/common/menu/joystickmenu.cpp index 18a1e5af6..40b0a4136 100644 --- a/source/common/menu/joystickmenu.cpp +++ b/source/common/menu/joystickmenu.cpp @@ -42,11 +42,11 @@ #include "c_bind.h" #include "d_event.h" #include "d_gui.h" +#include "input/m_joy.h" #define NO_IMP #include "optionmenuitems.h" -#if 0 // This requires the entire ZDoom backend to work. static TArray Joysticks; IJoystickConfig *SELECTED_JOYSTICK; @@ -245,10 +245,10 @@ public: mJoy = joy; } - bool Activate() + bool Activate(FName caller) override { UpdateJoystickConfigMenu(mJoy); - return FOptionMenuItemSubmenu::Activate(); + return FOptionMenuItemSubmenu::Activate(caller); } }; @@ -273,51 +273,50 @@ FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy) } if (joy == NULL) { - opt->mTitle = "Configure Controller"; - it = new FOptionMenuItemStaticText("Invalid controller specified for menu", false); + opt->mTitle = "$JOYMNU_TITLE"; + it = new FOptionMenuItemStaticText("$JOYMNU_INVALID"); opt->mItems.Push(it); } else { - opt->mTitle.Format("Configure %s", joy->GetName().GetChars()); + opt->mTitle.Format("%s", joy->GetName().GetChars()); SELECTED_JOYSTICK = joy; - it = new FOptionMenuSliderJoySensitivity("Overall sensitivity", 0, 2, 0.1, 3); + it = new FOptionMenuSliderJoySensitivity("$JOYMNU_OVRSENS", 0, 2, 0.1, 3); opt->mItems.Push(it); - it = new FOptionMenuItemStaticText(" ", false); + it = new FOptionMenuItemStaticText(" "); opt->mItems.Push(it); if (joy->GetNumAxes() > 0) { - it = new FOptionMenuItemStaticText("Axis Configuration", true); + it = new FOptionMenuItemStaticText("$JOYMNU_AXIS"); opt->mItems.Push(it); for (int i = 0; i < joy->GetNumAxes(); ++i) { - it = new FOptionMenuItemStaticText(" ", false); + it = new FOptionMenuItemStaticText(" "); opt->mItems.Push(it); it = new FOptionMenuItemJoyMap(joy->GetAxisName(i), i, "JoyAxisMapNames", false); opt->mItems.Push(it); - it = new FOptionMenuSliderJoyScale("Overall sensitivity", i, 0, 4, 0.1, 3); + it = new FOptionMenuSliderJoyScale("$JOYMNU_OVRSENS", i, 0, 4, 0.1, 3); opt->mItems.Push(it); - it = new FOptionMenuItemInverter("Invert", i, false); + it = new FOptionMenuItemInverter("$JOYMNU_INVERT", i, false); opt->mItems.Push(it); - it = new FOptionMenuSliderJoyDeadZone("Dead Zone", i, 0, 0.9, 0.05, 3); + it = new FOptionMenuSliderJoyDeadZone("$JOYMNU_DEADZONE", i, 0, 0.9, 0.05, 3); opt->mItems.Push(it); } } else { - it = new FOptionMenuItemStaticText("No configurable axes", false); + it = new FOptionMenuItemStaticText("$JOYMNU_NOAXES"); opt->mItems.Push(it); } } opt->mScrollPos = 0; opt->mSelectedItem = -1; opt->mIndent = 0; - opt->mPosition = -25; opt->CalcIndent(); return opt; } @@ -333,6 +332,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected) { FOptionMenuDescriptor *opt = (FOptionMenuDescriptor *)*desc; FOptionMenuItem *it; + for(unsigned i=0;imItems.Size();i++) { delete opt->mItems[i]; @@ -360,9 +360,9 @@ void UpdateJoystickMenu(IJoystickConfig *selected) } // Todo: Block joystick for changing this one. - it = new FOptionMenuItemOption("Enable controller support", "use_joystick", "YesNo", NULL, false); + it = new FOptionMenuItemOption("$JOYMNU_ENABLE", "use_joystick", "YesNo", NULL, false); opt->mItems.Push(it); - #ifdef _WIN32 + #if 0//def _WIN32 it = new FOptionMenuItemOption("Enable DirectInput controllers", "joy_dinput", "YesNo", NULL, false); opt->mItems.Push(it); it = new FOptionMenuItemOption("Enable XInput controllers", "joy_xinput", "YesNo", NULL, false); @@ -371,24 +371,24 @@ void UpdateJoystickMenu(IJoystickConfig *selected) opt->mItems.Push(it); #endif - it = new FOptionMenuItemStaticText(" ", false); + it = new FOptionMenuItemStaticText(" "); opt->mItems.Push(it); if (Joysticks.Size() == 0) { - it = new FOptionMenuItemStaticText("No controllers detected", false); + it = new FOptionMenuItemStaticText("$JOYMNU_NOCON"); opt->mItems.Push(it); if (!use_joystick) { - it = new FOptionMenuItemStaticText("Controller support must be", false); + it = new FOptionMenuItemStaticText("$JOYMNU_DISABLED1"); opt->mItems.Push(it); - it = new FOptionMenuItemStaticText("enabled to detect any", false); + it = new FOptionMenuItemStaticText("$JOYMNU_DISABLED1"); opt->mItems.Push(it); } } else { - it = new FOptionMenuItemStaticText("Configure controllers:", false); + it = new FOptionMenuItemStaticText("$JOYMNU_CONFIG"); opt->mItems.Push(it); for (int i = 0; i < (int)Joysticks.Size(); ++i) @@ -417,7 +417,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected) if (i == (int)Joysticks.Size()) { SELECTED_JOYSTICK = NULL; - if (DMenu::CurrentMenu != NULL && DMenu::CurrentMenu->IsKindOf(RUNTIME_CLASS(DJoystickConfigMenu))) + if (DMenu::CurrentMenu != NULL && dynamic_cast(DMenu::CurrentMenu)) { DMenu::CurrentMenu->Close(); } @@ -425,4 +425,9 @@ void UpdateJoystickMenu(IJoystickConfig *selected) } } -#endif \ No newline at end of file +static TMenuClassDescriptor _im("JoystickConfigMenu"); + +void RegisterJoystickMenus() +{ + menuClasses.Push(&_im); +} diff --git a/source/common/menu/menu.cpp b/source/common/menu/menu.cpp index 7285771d8..e3b9e7757 100644 --- a/source/common/menu/menu.cpp +++ b/source/common/menu/menu.cpp @@ -48,11 +48,12 @@ #include "printf.h" #include "v_draw.h" #include "gamecontrol.h" -#include "fx_man.h" #include "pragmas.h" #include "build.h" #include "baselayer.h" #include "statistics.h" +#include "input/m_joy.h" +#include "sound/s_soundinternal.h" void RegisterDukeMenus(); void RegisterRedneckMenus(); @@ -61,6 +62,8 @@ void RegisterSWMenus(); void RegisterPSMenus(); void RegisterLoadsaveMenus(); void RegisterOptionMenus(); +void RegisterJoystickMenus(); +void UpdateJoystickMenu(IJoystickConfig* joy); extern bool rotatesprite_2doverride; bool help_disabled, credits_disabled; int g_currentMenu; // accessible by CON scripts - contains the current menu's script ID if defined or INT_MAX if none given. @@ -364,7 +367,7 @@ void M_StartControlPanel (bool makeSound) created = true; M_CreateMenus(); } - FX_StopAllSounds(); + soundEngine->StopAllChannels(); gi->MenuOpened(); if (makeSound) gi->MenuSound(ActivateSound); @@ -957,8 +960,10 @@ void M_Init (void) RegisterPSMenus(); RegisterLoadsaveMenus(); RegisterOptionMenus(); + RegisterJoystickMenus(); timerSetCallback(M_Ticker); M_ParseMenuDefs(); + UpdateJoystickMenu(nullptr); } diff --git a/source/common/menu/messagebox.cpp b/source/common/menu/messagebox.cpp index 134358930..c66a185b9 100644 --- a/source/common/menu/messagebox.cpp +++ b/source/common/menu/messagebox.cpp @@ -108,7 +108,7 @@ void DMessageBoxMenu::Init(DMenu *parent, const char *message, int messagemode, if (playsound) { //S_StopSound (CHAN_VOICE); - //S_Sound (CHAN_VOICE | CHAN_UI, "menu/prompt", snd_menuvolume, ATTN_NONE); + //S_Sound (CHAN_VOICE | CHANF_UI, "menu/prompt", snd_menuvolume, ATTN_NONE); } } @@ -283,7 +283,7 @@ bool DMessageBoxMenu::MenuEvent(int mkey, bool fromcontroller) { if ((mkey == MKEY_Up || mkey == MKEY_Down) && m_generic_messagebox) { - //S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); + //S_Sound (CHAN_VOICE | CHANF_UI, "menu/cursor", snd_menuvolume, ATTN_NONE); messageSelection = !messageSelection; return true; } diff --git a/source/common/openaudio.cpp b/source/common/openaudio.cpp index 423a17525..32d5eac60 100644 --- a/source/common/openaudio.cpp +++ b/source/common/openaudio.cpp @@ -1,5 +1,5 @@ -#include "cache1d.h" + #include "openaudio.h" #include "gamecvars.h" diff --git a/source/common/rts.cpp b/source/common/rts.cpp index 372d12805..5ce19f36d 100644 --- a/source/common/rts.cpp +++ b/source/common/rts.cpp @@ -38,6 +38,7 @@ #include "filesystem/filesystem.h" #include "rts.h" #include "m_swap.h" +#include "s_soundinternal.h" struct WadInfo @@ -56,7 +57,7 @@ struct FileLump struct LumpInfoInternal { - int32_t position, size; + int32_t position, size, sid; }; //============= @@ -96,7 +97,7 @@ bool RTS_IsInitialized() LumpInfo.Resize(numlumps); for(unsigned i = 0; i < numlumps; i++, li++) { - LumpInfo[i] = { LittleLong(li->position), LittleLong(li->size) }; + LumpInfo[i] = { LittleLong(li->position), LittleLong(li->size), -1 }; if (unsigned(LumpInfo[i].position + LumpInfo[i].size) >= RTSFile.Size()) { LumpInfo[i].size = 0; // points to invalid data @@ -108,6 +109,19 @@ bool RTS_IsInitialized() } RTSFile.Reset(); LumpInfo.Reset(); + + // For the benefit of the sound system we have to link the RTS content into the file system. + // Unfortunately the file cannot be added directly because the internal names are meaningless. + int i = 0; + for (auto& li : LumpInfo) + { + if (li.size > 0) + { + FStringf rts("rts%02d", i); + int lump = fileSystem.AddFromBuffer(rts, "rts", (char*)RTSFile.Data() + li.position, li.size, -1, 0); + li.sid = soundEngine->AddSoundLump(rts, lump, 0, -1); + } + } return false; } @@ -127,3 +141,12 @@ void *RTS_GetSound(int lump) if(LumpInfo[lump].size <= 0) return nullptr; return RTSFile.Data() + LumpInfo[lump].position; } + +int RTS_GetSoundID(int lump) +{ + if (!RTS_IsInitialized()) return -1; + lump++; + if ((unsigned)lump >= LumpInfo.Size()) return -1; + if (LumpInfo[lump].size <= 0) return -1; + return LumpInfo[lump].sid; +} diff --git a/source/common/rts.h b/source/common/rts.h index f2a739c00..8ef937595 100644 --- a/source/common/rts.h +++ b/source/common/rts.h @@ -4,3 +4,4 @@ void RTS_Init(const char *filename); bool RTS_IsInitialized(); int RTS_SoundLength(int lump); void *RTS_GetSound(int lump); +int RTS_GetSoundID(int lump); diff --git a/source/common/screenshot.cpp b/source/common/screenshot.cpp new file mode 100644 index 000000000..305bbc24a --- /dev/null +++ b/source/common/screenshot.cpp @@ -0,0 +1,169 @@ +/* +** screenshot.cpp +** +**--------------------------------------------------------------------------- +** Copyright 2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "compat.h" +#include "build.h" +#include "baselayer.h" +#include "version.h" +#include "m_png.h" +#include "i_specialpaths.h" +#include "m_argv.h" +#include "cmdlib.h" +#include "gamecontrol.h" +#include "printf.h" +#include "c_dispatch.h" + +#include "../../glbackend/glbackend.h" + +EXTERN_CVAR(Float, png_gamma) +// +// screencapture +// + +static FileWriter *opennextfile(const char *fn) +{ + static int count = 0; + FString name; + do + { + name.Format(fn, count++); + } while (FileExists(name)); + return FileWriter::Open(name); +} + +static void getScreen(uint8_t* imgBuf) +{ + GLInterface.ReadPixels(xdim, ydim, imgBuf); +} + + +CVAR(String, screenshotname, "", CVAR_ARCHIVE) // not GLOBALCONFIG - allow setting this per game. +CVAR(String, screenshot_dir, "", CVAR_ARCHIVE) // same here. + +// +// WritePNGfile +// +static void WritePNGfile(FileWriter* file, const uint8_t* buffer, const PalEntry* palette, + ESSType color_type, int width, int height, int pitch, float gamma) +{ + FStringf software("Demolition %s", GetVersionString()); + if (!M_CreatePNG(file, buffer, palette, color_type, width, height, pitch, gamma) || + !M_AppendPNGText(file, "Software", software) || + !M_FinishPNG(file)) + { + Printf("Failed writing screenshot\n"); + } +} + + +static int SaveScreenshot() +{ + PalEntry Palette[256]; + + size_t dirlen; + FString autoname = Args->CheckValue("-shotdir"); + if (autoname.IsEmpty()) + { + autoname = screenshot_dir; + } + dirlen = autoname.Len(); + if (dirlen == 0) + { + autoname = M_GetScreenshotsPath(); + dirlen = autoname.Len(); + } + if (dirlen > 0) + { + if (autoname[dirlen - 1] != '/' && autoname[dirlen - 1] != '\\') + { + autoname += '/'; + } + } + autoname = NicePath(autoname); + CreatePath(autoname); + + if (**screenshotname) autoname << screenshotname; + else autoname << currentGame; + autoname << "_%04d.png"; + FileWriter *fil = opennextfile(autoname); + + if (fil == nullptr) + { + return -1; + } + + auto truecolor = videoGetRenderMode() >= REND_POLYMOST; + TArray imgBuf(xdim * ydim * (truecolor ? 3 : 1), true); + + videoBeginDrawing(); + + if (truecolor) + { + getScreen(imgBuf.Data()); + int bytesPerLine = xdim * 3; + + TArray rowBuf(bytesPerLine * 3, true); + + for (int i = 0, numRows = ydim >> 1; i < numRows; ++i) + { + memcpy(rowBuf.Data(), imgBuf.Data() + i * bytesPerLine, bytesPerLine); + memcpy(imgBuf.Data() + i * bytesPerLine, imgBuf.Data() + (ydim - i - 1) * bytesPerLine, bytesPerLine); + memcpy(imgBuf.Data() + (ydim - i - 1) * bytesPerLine, rowBuf.Data(), bytesPerLine); + } + } + else + { + for (int i = 0; i < 256; ++i) + { + Palette[i].r = curpalettefaded[i].r; + Palette[i].g = curpalettefaded[i].g; + Palette[i].b = curpalettefaded[i].b; + } + + for (int i = 0; i < ydim; ++i) + memcpy(imgBuf.Data() + i * xdim, (uint8_t *)frameplace + ylookup[i], xdim); + } + + videoEndDrawing(); + + WritePNGfile(fil, imgBuf.Data(), Palette, truecolor ? SS_RGB : SS_PAL, xdim, ydim, truecolor? xdim*3 : xdim, png_gamma); + delete fil; + Printf("screenshot saved\n"); + return 0; +} + +CCMD(screenshot) +{ + SaveScreenshot(); +} + diff --git a/source/common/music/backend/efx.h b/source/common/sound/backend/efx.h similarity index 100% rename from source/common/music/backend/efx.h rename to source/common/sound/backend/efx.h diff --git a/source/common/music/backend/i_sound.cpp b/source/common/sound/backend/i_sound.cpp similarity index 97% rename from source/common/music/backend/i_sound.cpp rename to source/common/sound/backend/i_sound.cpp index 996e75bbe..72226695a 100644 --- a/source/common/music/backend/i_sound.cpp +++ b/source/common/sound/backend/i_sound.cpp @@ -249,6 +249,8 @@ void I_InitSound () { FModule_SetProgDir(progdir); /* Get command line options: */ + nosound = !!Args->CheckParm ("-nosound"); + nosfx = !!Args->CheckParm ("-nosfx"); GSnd = NULL; if (nosound) @@ -266,7 +268,7 @@ void I_InitSound () { I_CloseSound(); GSnd = new NullSoundRenderer; - Printf (TEXTCOLOR_RED"Music init failed. Using nosound.\n"); + Printf (TEXTCOLOR_RED"Sound init failed. Using nosound.\n"); } snd_sfxvolume.Callback (); } @@ -274,8 +276,8 @@ void I_InitSound () void I_CloseSound () { - // Free all loaded samples - //S_UnloadAllSounds(); + // Free all loaded samples. Beware that the sound engine may already have been deleted. + if (soundEngine) soundEngine->UnloadAllSounds(); delete GSnd; GSnd = NULL; @@ -398,7 +400,7 @@ std::pair SoundRenderer::LoadSoundVoc(uint8_t *sfxdata, int le if (codec == 0) bits = 8; else if (codec == 4) - bits = -16; + bits = 16; else okay = false; len += blocksize - 2; } @@ -449,7 +451,7 @@ std::pair SoundRenderer::LoadSoundVoc(uint8_t *sfxdata, int le if (codec == 0) bits = 8; else if (codec == 4) - bits = -16; + bits = 16; else okay = false; len += blocksize - 12; } else okay = false; diff --git a/source/common/music/backend/i_sound.h b/source/common/sound/backend/i_sound.h similarity index 96% rename from source/common/music/backend/i_sound.h rename to source/common/sound/backend/i_sound.h index 0b8685ae1..16c6cdcdd 100644 --- a/source/common/music/backend/i_sound.h +++ b/source/common/sound/backend/i_sound.h @@ -175,11 +175,7 @@ extern bool nosfx; extern bool nosound; void I_InitSound (); - -void S_ChannelEnded(FISoundChannel *schan); -void S_ChannelVirtualChanged(FISoundChannel *schan, bool is_virtual); -float S_GetRolloff(FRolloffInfo *rolloff, float distance, bool logarithmic); -FISoundChannel *S_GetChannel(void *syschan); +void I_CloseSound(); extern ReverbContainer *DefaultEnvironments[26]; diff --git a/source/common/music/backend/i_soundinternal.h b/source/common/sound/backend/i_soundinternal.h similarity index 73% rename from source/common/music/backend/i_soundinternal.h rename to source/common/sound/backend/i_soundinternal.h index d841693a7..08dd311a2 100644 --- a/source/common/music/backend/i_soundinternal.h +++ b/source/common/sound/backend/i_soundinternal.h @@ -8,6 +8,33 @@ #include "tarray.h" #include "zmusic/sounddecoder.h" #include "../../libraries/music_common/fileio.h" +#include "tflags.h" + +enum EChanFlag +{ + // modifier flags + CHANF_LISTENERZ = 8, + CHANF_MAYBE_LOCAL = 16, + CHANF_UI = 32, // Do not record sound in savegames. + CHANF_NOPAUSE = 64, // Do not pause this sound in menus. + CHANF_AREA = 128, // Sound plays from all around. Only valid with sector sounds. + CHANF_LOOP = 256, + + CHANF_PICKUP = CHANF_MAYBE_LOCAL, + + CHANF_NONE = 0, + CHANF_IS3D = 1, // internal: Sound is 3D. + CHANF_EVICTED = 2, // internal: Sound was evicted. + CHANF_FORGETTABLE = 4, // internal: Forget channel data when sound stops. + CHANF_JUSTSTARTED = 512, // internal: Sound has not been updated yet. + CHANF_ABSTIME = 1024, // internal: Start time is absolute and does not depend on current time. + CHANF_VIRTUAL = 2048, // internal: Channel is currently virtual + CHANF_NOSTOP = 4096, // only for A_PlaySound. Does not start if channel is playing something. + CHANF_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them. +}; + +typedef TFlags EChanFlags; +DEFINE_TFLAGS_OPERATORS(EChanFlags) class FileReader; @@ -77,6 +104,7 @@ struct SoundListener bool underwater; bool valid; ReverbContainer *Environment; + void* ListenerObject; }; // Default rolloff information. @@ -111,7 +139,7 @@ struct FISoundChannel float DistanceScale; float DistanceSqr; bool ManualRolloff; - int ChanFlags; + EChanFlags ChanFlags; }; @@ -121,4 +149,5 @@ class SoundStream; + #endif diff --git a/source/common/music/backend/oalload.h b/source/common/sound/backend/oalload.h similarity index 100% rename from source/common/music/backend/oalload.h rename to source/common/sound/backend/oalload.h diff --git a/source/common/music/backend/oalsound.cpp b/source/common/sound/backend/oalsound.cpp similarity index 96% rename from source/common/music/backend/oalsound.cpp rename to source/common/sound/backend/oalsound.cpp index 5506e445b..327129335 100644 --- a/source/common/music/backend/oalsound.cpp +++ b/source/common/sound/backend/oalsound.cpp @@ -43,7 +43,6 @@ #include "cmdlib.h" #include "c_cvars.h" #include "printf.h" -#include "menu.h" #include "zmusic/sounddecoder.h" #include "filereadermusicinterface.h" @@ -54,6 +53,11 @@ FModule OpenALModule{"OpenAL"}; #include "oalload.h" +CUSTOM_CVAR(Int, snd_channels, 128, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // number of channels available +{ + if (self < 64) self = 64; +} +CVAR(Bool, snd_waterreverb, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR (String, snd_aldevice, "Default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, snd_efx, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, snd_alresampler, "Default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -97,58 +101,6 @@ bool IsOpenALPresent() -void I_BuildALDeviceList(FOptionValues *opt) -{ - opt->mValues.Resize(1); - opt->mValues[0].TextValue = "Default"; - opt->mValues[0].Text = "Default"; - -#ifndef NO_OPENAL - if (IsOpenALPresent()) - { - const ALCchar *names = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ? - alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) : - alcGetString(NULL, ALC_DEVICE_SPECIFIER)); - if (!names) - Printf("Failed to get device list: %s\n", alcGetString(NULL, alcGetError(NULL))); - else while (*names) - { - unsigned int i = opt->mValues.Reserve(1); - opt->mValues[i].TextValue = names; - opt->mValues[i].Text = names; - - names += strlen(names) + 1; - } - } -#endif -} - -void I_BuildALResamplersList(FOptionValues *opt) -{ - opt->mValues.Resize(1); - opt->mValues[0].TextValue = "Default"; - opt->mValues[0].Text = "Default"; - -#ifndef NO_OPENAL - if (!IsOpenALPresent()) - return; - if (!alcGetCurrentContext() || !alIsExtensionPresent("AL_SOFT_source_resampler")) - return; - - LPALGETSTRINGISOFT alGetStringiSOFT = reinterpret_cast(alGetProcAddress("alGetStringiSOFT")); - ALint num_resamplers = alGetInteger(AL_NUM_RESAMPLERS_SOFT); - - unsigned int idx = opt->mValues.Reserve(num_resamplers); - for(ALint i = 0;i < num_resamplers;++i) - { - const ALchar *name = alGetStringiSOFT(AL_RESAMPLER_NAME_SOFT, i); - opt->mValues[idx].TextValue = name; - opt->mValues[idx].Text = name; - ++idx; - } -#endif -} - ReverbContainer *ForcedEnvironment; @@ -156,10 +108,7 @@ ReverbContainer *ForcedEnvironment; #ifndef NO_OPENAL -//EXTERN_CVAR (Int, snd_channels) -int snd_channels; EXTERN_CVAR (Int, snd_samplerate) -EXTERN_CVAR (Bool, snd_waterreverb) EXTERN_CVAR (Bool, snd_pitched) EXTERN_CVAR (Int, snd_hrtf) @@ -239,11 +188,10 @@ class OpenALSoundStream : public SoundStream /* Get a source, killing the farthest, lowest-priority sound if needed */ if(Renderer->FreeSfx.Size() == 0) { - /* FSoundChan *lowest = Renderer->FindLowestChannel(); if(lowest) Renderer->ForceStopChannel(lowest); - if(Renderer->FreeSfx.Size() == 0)*/ + if(Renderer->FreeSfx.Size() == 0) return false; } Renderer->FreeSfx.Pop(Source); @@ -547,26 +495,7 @@ static size_t GetChannelCount(ChannelConfig chans) static float GetRolloff(const FRolloffInfo *rolloff, float distance) { -#if 0 - if(distance <= rolloff->MinDistance) - return 1.f; - // Logarithmic rolloff has no max distance where it goes silent. - if(rolloff->RolloffType == ROLLOFF_Log) - return rolloff->MinDistance / - (rolloff->MinDistance + rolloff->RolloffFactor*(distance-rolloff->MinDistance)); - if(distance >= rolloff->MaxDistance) - return 0.f; - - float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance); - if(rolloff->RolloffType == ROLLOFF_Linear) - return volume; - - if(rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve.Size() > 0) - return S_SoundCurve[int(S_SoundCurve.Size() * (1.f - volume))] / 127.f; - return (powf(10.f, volume) - 1.f) / 9.f; -#else - return 0; -#endif + return soundEngine->GetRolloff(rolloff, distance); } ALCdevice *OpenALSoundRenderer::InitDevice() @@ -988,10 +917,10 @@ void OpenALSoundRenderer::RemoveStream(OpenALSoundStream *stream) void OpenALSoundRenderer::SetSfxVolume(float volume) { -#if 0 SfxVolume = volume; - FSoundChan *schan = Channels; + if (!soundEngine) return; + FSoundChan *schan = soundEngine->GetChannels(); while(schan) { if(schan->SysChannel != NULL) @@ -1009,7 +938,6 @@ void OpenALSoundRenderer::SetSfxVolume(float volume) alProcessUpdatesSOFT(); getALError(); -#endif } void OpenALSoundRenderer::SetMusicVolume(float volume) @@ -1364,12 +1292,11 @@ std::pair OpenALSoundRenderer::LoadSoundBuffered(FSoundLoadBu void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) { -#if 0 if(!sfx.data) return; ALuint buffer = GET_PTRID(sfx.data); - FSoundChan *schan = Channels; + FSoundChan *schan = soundEngine->GetChannels(); while(schan) { if(schan->SysChannel) @@ -1403,7 +1330,6 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx) alDeleteBuffers(1, &buffer); getALError(); -#endif } @@ -1422,7 +1348,6 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) { -#if 0 if(FreeSfx.Size() == 0) { FSoundChan *lowest = FindLowestChannel(); @@ -1507,7 +1432,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int FreeSfx.Pop(); FISoundChannel *chan = reuse_chan; - if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); + if(!chan) chan = soundEngine->GetChannel(MAKE_PTRID(source)); else chan->SysChannel = MAKE_PTRID(source); chan->Rolloff.RolloffType = ROLLOFF_Log; @@ -1517,16 +1442,12 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int chan->ManualRolloff = false; return chan; -#else - return 0; -#endif } FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FISoundChannel *reuse_chan) { -#if 0 float dist_sqr = (float)(pos - listener->position).LengthSquared(); if(FreeSfx.Size() == 0) @@ -1605,7 +1526,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener * distance that corresponds to the area radius. */ alSourcef(source, AL_SOURCE_RADIUS, (chanflags&SNDF_AREA) ? // Clamp in case the max distance is <= the area radius - 1.f/MAX(GetRolloff(rolloff, AREA_SOUND_RADIUS), 0.00001f) : 0.f + 1.f/std::max(GetRolloff(rolloff, AREA_SOUND_RADIUS), 0.00001f) : 0.f ); } else if((chanflags&SNDF_AREA) && dist_sqr < AREA_SOUND_RADIUS*AREA_SOUND_RADIUS) @@ -1722,7 +1643,7 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener FreeSfx.Pop(); FISoundChannel *chan = reuse_chan; - if(!chan) chan = S_GetChannel(MAKE_PTRID(source)); + if(!chan) chan = soundEngine->GetChannel(MAKE_PTRID(source)); else chan->SysChannel = MAKE_PTRID(source); chan->Rolloff = *rolloff; @@ -1730,9 +1651,6 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener chan->ManualRolloff = manualRolloff; return chan; -#else - return 0; -#endif } void OpenALSoundRenderer::ChannelVolume(FISoundChannel *chan, float volume) @@ -1753,13 +1671,11 @@ void OpenALSoundRenderer::ChannelPitch(FISoundChannel *chan, float pitch) alDeferUpdatesSOFT(); -#if 0 ALuint source = GET_PTRID(chan->SysChannel); - if (WasInWater && !(chan->ChanFlags & CHAN_UI)) + if (WasInWater && !(chan->ChanFlags & CHANF_UI)) alSourcef(source, AL_PITCH, std::max(pitch, 0.0001f)*PITCH_MULT); else alSourcef(source, AL_PITCH, std::max(pitch, 0.0001f)); -#endif } void OpenALSoundRenderer::FreeSource(ALuint source) @@ -1786,9 +1702,8 @@ void OpenALSoundRenderer::StopChannel(FISoundChannel *chan) ALuint source = GET_PTRID(chan->SysChannel); // Release first, so it can be properly marked as evicted if it's being killed -#if 0 - S_ChannelEnded(chan); -#endif + soundEngine->ChannelEnded(chan); + ALint state = AL_INITIAL; alGetSourcei(source, AL_SOURCE_STATE, &state); if(state != AL_PLAYING) @@ -1811,9 +1726,7 @@ void OpenALSoundRenderer::ForceStopChannel(FISoundChannel *chan) ALuint source = GET_PTRID(chan->SysChannel); if(!source) return; -#if 0 - S_ChannelEnded(chan); -#endif + soundEngine->ChannelEnded(chan); FreeSource(source); } @@ -1971,7 +1884,6 @@ void OpenALSoundRenderer::UpdateSoundParams3D(SoundListener *listener, FISoundCh void OpenALSoundRenderer::UpdateListener(SoundListener *listener) { -#if 0 if(!listener->valid) return; @@ -2034,11 +1946,11 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); // Apply the updated filters on the sources - FSoundChan *schan = Channels; + FSoundChan *schan = soundEngine->GetChannels(); while (schan) { ALuint source = GET_PTRID(schan->SysChannel); - if (source && !(schan->ChanFlags & CHAN_UI)) + if (source && !(schan->ChanFlags & CHANF_UI)) { alSourcei(source, AL_DIRECT_FILTER, EnvFilters[0]); alSource3i(source, AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); @@ -2047,11 +1959,11 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) } } - FSoundChan *schan = Channels; + FSoundChan *schan = soundEngine->GetChannels(); while (schan) { ALuint source = GET_PTRID(schan->SysChannel); - if (source && !(schan->ChanFlags & CHAN_UI)) + if (source && !(schan->ChanFlags & CHANF_UI)) alSourcef(source, AL_PITCH, schan->Pitch / 128.0f * PITCH_MULT); schan = schan->NextChan; } @@ -2072,11 +1984,11 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) alFilterf(EnvFilters[1], AL_LOWPASS_GAIN, 1.f); alFilterf(EnvFilters[1], AL_LOWPASS_GAINHF, 1.f); - FSoundChan *schan = Channels; + FSoundChan *schan = soundEngine->GetChannels(); while (schan) { ALuint source = GET_PTRID(schan->SysChannel); - if (source && !(schan->ChanFlags & CHAN_UI)) + if (source && !(schan->ChanFlags & CHANF_UI)) { alSourcei(source, AL_DIRECT_FILTER, EnvFilters[0]); alSource3i(source, AL_AUXILIARY_SEND_FILTER, EnvSlot, 0, EnvFilters[1]); @@ -2085,17 +1997,16 @@ void OpenALSoundRenderer::UpdateListener(SoundListener *listener) } } - FSoundChan *schan = Channels; + FSoundChan *schan = soundEngine->GetChannels(); while (schan) { ALuint source = GET_PTRID(schan->SysChannel); - if (source && !(schan->ChanFlags & CHAN_UI)) + if (source && !(schan->ChanFlags & CHANF_UI)) alSourcef(source, AL_PITCH, schan->Pitch / 128.0f); schan = schan->NextChan; } getALError(); } -#endif } void OpenALSoundRenderer::UpdateSounds() @@ -2118,7 +2029,7 @@ void OpenALSoundRenderer::UpdateSounds() ++iter; } } -#if 0 + if(ALC.EXT_disconnect) { ALCint connected = ALC_TRUE; @@ -2126,11 +2037,10 @@ void OpenALSoundRenderer::UpdateSounds() if(connected == ALC_FALSE) { Printf("Sound device disconnected; restarting...\n"); - S_SoundReset(); + soundEngine->Reset(); return; } } -#endif PurgeStoppedSources(); } @@ -2254,7 +2164,6 @@ void OpenALSoundRenderer::PrintDriversList() void OpenALSoundRenderer::PurgeStoppedSources() { -#if 0 // Release channels that are stopped for(uint32_t i = 0;i < SfxGroup.Size();++i) { @@ -2264,7 +2173,7 @@ void OpenALSoundRenderer::PurgeStoppedSources() if(state == AL_INITIAL || state == AL_PLAYING || state == AL_PAUSED) continue; - FSoundChan *schan = Channels; + FSoundChan *schan = soundEngine->GetChannels(); while(schan) { if(schan->SysChannel != NULL && src == GET_PTRID(schan->SysChannel)) @@ -2276,7 +2185,6 @@ void OpenALSoundRenderer::PurgeStoppedSources() } } getALError(); -#endif } void OpenALSoundRenderer::LoadReverb(const ReverbContainer *env) @@ -2387,8 +2295,7 @@ void OpenALSoundRenderer::LoadReverb(const ReverbContainer *env) FSoundChan *OpenALSoundRenderer::FindLowestChannel() { -#if 0 - FSoundChan *schan = Channels; + FSoundChan *schan = soundEngine->GetChannels(); FSoundChan *lowest = NULL; while(schan) { @@ -2402,8 +2309,60 @@ FSoundChan *OpenALSoundRenderer::FindLowestChannel() schan = schan->NextChan; } return lowest; -#else - return 0; +} + + +#include "menu/menu.h" + +void I_BuildALDeviceList(FOptionValues* opt) +{ + opt->mValues.Resize(1); + opt->mValues[0].TextValue = "Default"; + opt->mValues[0].Text = "Default"; + +#ifndef NO_OPENAL + if (IsOpenALPresent()) + { + const ALCchar* names = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ? + alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) : + alcGetString(NULL, ALC_DEVICE_SPECIFIER)); + if (!names) + Printf("Failed to get device list: %s\n", alcGetString(NULL, alcGetError(NULL))); + else while (*names) + { + unsigned int i = opt->mValues.Reserve(1); + opt->mValues[i].TextValue = names; + opt->mValues[i].Text = names; + + names += strlen(names) + 1; + } + } +#endif +} + +void I_BuildALResamplersList(FOptionValues* opt) +{ + opt->mValues.Resize(1); + opt->mValues[0].TextValue = "Default"; + opt->mValues[0].Text = "Default"; + +#ifndef NO_OPENAL + if (!IsOpenALPresent()) + return; + if (!alcGetCurrentContext() || !alIsExtensionPresent("AL_SOFT_source_resampler")) + return; + + LPALGETSTRINGISOFT alGetStringiSOFT = reinterpret_cast(alGetProcAddress("alGetStringiSOFT")); + ALint num_resamplers = alGetInteger(AL_NUM_RESAMPLERS_SOFT); + + unsigned int idx = opt->mValues.Reserve(num_resamplers); + for (ALint i = 0; i < num_resamplers; ++i) + { + const ALchar* name = alGetStringiSOFT(AL_RESAMPLER_NAME_SOFT, i); + opt->mValues[idx].TextValue = name; + opt->mValues[idx].Text = name; + ++idx; + } #endif } diff --git a/source/common/music/backend/oalsound.h b/source/common/sound/backend/oalsound.h similarity index 99% rename from source/common/music/backend/oalsound.h rename to source/common/sound/backend/oalsound.h index 9624a2726..266d1f232 100644 --- a/source/common/music/backend/oalsound.h +++ b/source/common/sound/backend/oalsound.h @@ -8,7 +8,7 @@ #include #include "i_sound.h" -//#include "s_sound.h" +#include "s_soundinternal.h" #ifndef NO_OPENAL diff --git a/source/common/sound/s_environment.cpp b/source/common/sound/s_environment.cpp new file mode 100644 index 000000000..69c582c9c --- /dev/null +++ b/source/common/sound/s_environment.cpp @@ -0,0 +1,630 @@ +/* +** +** +**--------------------------------------------------------------------------- +** Copyright 2005-2016 Randy Heit +** Copyright 2005-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "s_soundinternal.h" +#include "sc_man.h" +#include "templates.h" + + +FReverbField ReverbFields[] = +{ + { 0, 25, 0, &REVERB_PROPERTIES::Environment, 0 }, + { 1000, 100000, &REVERB_PROPERTIES::EnvSize, 0, 0 }, + { 0, 1000, &REVERB_PROPERTIES::EnvDiffusion, 0, 0 }, + { -10000, 0, 0, &REVERB_PROPERTIES::Room, 0 }, + { -10000, 0, 0, &REVERB_PROPERTIES::RoomHF, 0 }, + { -10000, 0, 0, &REVERB_PROPERTIES::RoomLF, 0 }, + { 100, 20000, &REVERB_PROPERTIES::DecayTime, 0, 0 }, + { 100, 2000, &REVERB_PROPERTIES::DecayHFRatio, 0, 0 }, + { 100, 2000, &REVERB_PROPERTIES::DecayLFRatio, 0, 0 }, + { -10000, 1000, 0, &REVERB_PROPERTIES::Reflections, 0 }, + { 0, 300, &REVERB_PROPERTIES::ReflectionsDelay, 0, 0 }, + { -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan0, 0, 0 }, + { -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan1, 0, 0 }, + { -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan2, 0, 0 }, + { -10000, 2000, 0, &REVERB_PROPERTIES::Reverb, 0 }, + { 0, 100, &REVERB_PROPERTIES::ReverbDelay, 0, 0 }, + { -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan0, 0, 0 }, + { -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan1, 0, 0 }, + { -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan2, 0, 0 }, + { 75, 250, &REVERB_PROPERTIES::EchoTime, 0, 0 }, + { 0, 1000, &REVERB_PROPERTIES::EchoDepth, 0, 0 }, + { 40, 4000, &REVERB_PROPERTIES::ModulationTime, 0, 0 }, + { 0, 1000, &REVERB_PROPERTIES::ModulationDepth, 0, 0 }, + { -100000, 0, &REVERB_PROPERTIES::AirAbsorptionHF, 0, 0 }, + { 1000000, 20000000, &REVERB_PROPERTIES::HFReference, 0, 0 }, + { 20000, 1000000, &REVERB_PROPERTIES::LFReference, 0, 0 }, + { 0, 10000, &REVERB_PROPERTIES::RoomRolloffFactor, 0, 0 }, + { 0, 100000, &REVERB_PROPERTIES::Diffusion, 0, 0 }, + { 0, 100000, &REVERB_PROPERTIES::Density, 0, 0 }, + { 0, 0, 0, 0, 1 }, + { 0, 0, 0, 0, 2 }, + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 5 }, + { 0, 0, 0, 0, 3 }, + { 0, 0, 0, 0, 4 }, + { 0, 0, 0, 0, 6 }, + { 0, 0, 0, 0, 7 } +}; +#define NUM_REVERB_FIELDS (int(countof(ReverbFields))) +int NumReverbs = NUM_REVERB_FIELDS; + +const char *ReverbFieldNames[NUM_REVERB_FIELDS+2] = +{ + "Environment", + "EnvironmentSize", + "EnvironmentDiffusion", + "Room", + "RoomHF", + "RoomLF", + "DecayTime", + "DecayHFRatio", + "DecayLFRatio", + "Reflections", + "ReflectionsDelay", + "ReflectionsPanX", + "ReflectionsPanY", + "ReflectionsPanZ", + "Reverb", + "ReverbDelay", + "ReverbPanX", + "ReverbPanY", + "ReverbPanZ", + "EchoTime", + "EchoDepth", + "ModulationTime", + "ModulationDepth", + "AirAbsorptionHF", + "HFReference", + "LFReference", + "RoomRolloffFactor", + "Diffusion", + "Density", + "bReflectionsScale", + "bReflectionsDelayScale", + "bDecayTimeScale", + "bDecayHFLimit", + "bReverbScale", + "bReverbDelayScale", + "bEchoTimeScale", + "bModulationTimeScale", + "}", + NULL +}; + +static const char *BoolNames[3] = { "False", "True", NULL }; + +static ReverbContainer DSPWater = +{ + // Based on the "off" reverb, this one uses the software water effect, + // which is completely independant from EAX-like reverb. + NULL, + "DSP Water", + 0xffff, + true, + false, + {0, 0, 7.5f, 1.00f, -10000, -10000, 0, 1.00f, 1.00f, 1.0f, -2602, 0.007f, 0.0f,0.0f,0.0f, 200, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 0.0f, 0.0f, 0x33f }, + true +}; + +static ReverbContainer Psychotic = +{ + &DSPWater, + "Psychotic", + 0x1900, + true, + false, + {0,25, 1.0f, 0.50f, -1000, -151, 0, 7.56f, 0.91f, 1.0f, -626, 0.020f, 0.0f,0.0f,0.0f, 774, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 4.00f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }, + false +}; + +static ReverbContainer Dizzy = +{ + &Psychotic, + "Dizzy", + 0x1800, + true, + false, + {0,24, 1.8f, 0.60f, -1000, -400, 0, 17.23f, 0.56f, 1.0f, -1713, 0.020f, 0.0f,0.0f,0.0f, -613, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 1.00f, 0.81f, 0.310f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }, + false +}; + +static ReverbContainer Drugged = +{ + &Dizzy, + "Drugged", + 0x1700, + true, + false, + {0,23, 1.9f, 0.50f, -1000, 0, 0, 8.39f, 1.39f, 1.0f, -115, 0.002f, 0.0f,0.0f,0.0f, 985, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }, + false +}; + +static ReverbContainer Underwater = +{ + &Drugged, + "Underwater", + 0x1600, + true, + false, + {0,22, 1.8f, 1.00f, -1000, -4000, 0, 1.49f, 0.10f, 1.0f, -449, 0.007f, 0.0f,0.0f,0.0f, 1700, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 1.18f, 0.348f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer SewerPipe = +{ + &Underwater, + "Sewer Pipe", + 0x1500, + true, + false, + {0,21, 1.7f, 0.80f, -1000, -1000, 0, 2.81f, 0.14f, 1.0f, 429, 0.014f, 0.0f,0.0f,0.0f, 1023, 0.021f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 80.0f, 60.0f, 0x3f }, + false +}; + +static ReverbContainer ParkingLot = +{ + &SewerPipe, + "Parking Lot", + 0x1400, + true, + false, + {0,20, 8.3f, 1.00f, -1000, 0, 0, 1.65f, 1.50f, 1.0f, -1363, 0.008f, 0.0f,0.0f,0.0f, -1153, 0.012f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }, + false +}; + +static ReverbContainer Plain = +{ + &ParkingLot, + "Plain", + 0x1300, + true, + false, + {0,19, 42.5f, 0.21f, -1000, -2000, 0, 1.49f, 0.50f, 1.0f, -2466, 0.179f, 0.0f,0.0f,0.0f, -1926, 0.100f, 0.0f,0.0f,0.0f, 0.250f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 21.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Quarry = +{ + &Plain, + "Quarry", + 0x1200, + true, + false, + {0,18, 17.5f, 1.00f, -1000, -1000, 0, 1.49f, 0.83f, 1.0f, -10000, 0.061f, 0.0f,0.0f,0.0f, 500, 0.025f, 0.0f,0.0f,0.0f, 0.125f, 0.70f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Mountains = +{ + &Quarry, + "Mountains", + 0x1100, + true, + false, + {0,17, 100.0f, 0.27f, -1000, -2500, 0, 1.49f, 0.21f, 1.0f, -2780, 0.300f, 0.0f,0.0f,0.0f, -1434, 0.100f, 0.0f,0.0f,0.0f, 0.250f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 27.0f, 100.0f, 0x1f }, + false +}; + +static ReverbContainer City = +{ + &Mountains, + "City", + 0x1000, + true, + false, + {0,16, 7.5f, 0.50f, -1000, -800, 0, 1.49f, 0.67f, 1.0f, -2273, 0.007f, 0.0f,0.0f,0.0f, -1691, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 50.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Forest = +{ + &City, + "Forest", + 0x0F00, + true, + false, + {0,15, 38.0f, 0.30f, -1000, -3300, 0, 1.49f, 0.54f, 1.0f, -2560, 0.162f, 0.0f,0.0f,0.0f, -229, 0.088f, 0.0f,0.0f,0.0f, 0.125f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 79.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Alley = +{ + &Forest, + "Alley", + 0x0E00, + true, + false, + {0,14, 7.5f, 0.30f, -1000, -270, 0, 1.49f, 0.86f, 1.0f, -1204, 0.007f, 0.0f,0.0f,0.0f, -4, 0.011f, 0.0f,0.0f,0.0f, 0.125f, 0.95f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer StoneCorridor = +{ + &Alley, + "Stone Corridor", + 0x0D00, + true, + false, + {0,13, 13.5f, 1.00f, -1000, -237, 0, 2.70f, 0.79f, 1.0f, -1214, 0.013f, 0.0f,0.0f,0.0f, 395, 0.020f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Hallway = +{ + &StoneCorridor, + "Hallway", + 0x0C00, + true, + false, + {0,12, 1.8f, 1.00f, -1000, -300, 0, 1.49f, 0.59f, 1.0f, -1219, 0.007f, 0.0f,0.0f,0.0f, 441, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer CarpettedHallway = +{ + &Hallway, + "Carpetted Hallway", + 0x0B00, + true, + false, + {0,11, 1.9f, 1.00f, -1000, -4000, 0, 0.30f, 0.10f, 1.0f, -1831, 0.002f, 0.0f,0.0f,0.0f, -1630, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Hangar = +{ + &CarpettedHallway, + "Hangar", + 0x0A00, + true, + false, + {0,10, 50.3f, 1.00f, -1000, -1000, 0, 10.05f, 0.23f, 1.0f, -602, 0.020f, 0.0f,0.0f,0.0f, 198, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Arena = +{ + &Hangar, + "Arena", + 0x0900, + true, + false, + {0, 9, 36.2f, 1.00f, -1000, -698, 0, 7.24f, 0.33f, 1.0f, -1166, 0.020f, 0.0f,0.0f,0.0f, 16, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Cave = +{ + &Arena, + "Cave", + 0x0800, + true, + false, + {0, 8, 14.6f, 1.00f, -1000, 0, 0, 2.91f, 1.30f, 1.0f, -602, 0.015f, 0.0f,0.0f,0.0f, -302, 0.022f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f }, + false +}; + +static ReverbContainer ConcertHall = +{ + &Cave, + "Concert Hall", + 0x0700, + true, + false, + {0, 7, 19.6f, 1.00f, -1000, -500, 0, 3.92f, 0.70f, 1.0f, -1230, 0.020f, 0.0f,0.0f,0.0f, -2, 0.029f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Auditorium = +{ + &ConcertHall, + "Auditorium", + 0x0600, + true, + false, + {0, 6, 21.6f, 1.00f, -1000, -476, 0, 4.32f, 0.59f, 1.0f, -789, 0.020f, 0.0f,0.0f,0.0f, -289, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer StoneRoom = +{ + &Auditorium, + "Stone Room", + 0x0500, + true, + false, + {0, 5, 11.6f, 1.00f, -1000, -300, 0, 2.31f, 0.64f, 1.0f, -711, 0.012f, 0.0f,0.0f,0.0f, 83, 0.017f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer LivingRoom = +{ + &StoneRoom, + "Living Room", + 0x0400, + true, + false, + {0, 4, 2.5f, 1.00f, -1000, -6000, 0, 0.50f, 0.10f, 1.0f, -1376, 0.003f, 0.0f,0.0f,0.0f, -1104, 0.004f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Bathroom = +{ + &LivingRoom, + "Bathroom", + 0x0300, + true, + false, + {0, 3, 1.4f, 1.00f, -1000, -1200, 0, 1.49f, 0.54f, 1.0f, -370, 0.007f, 0.0f,0.0f,0.0f, 1030, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 60.0f, 0x3f }, + false +}; + +static ReverbContainer Room = +{ + &Bathroom, + "Room", + 0x0200, + true, + false, + {0, 2, 1.9f, 1.00f, -1000, -454, 0, 0.40f, 0.83f, 1.0f, -1646, 0.002f, 0.0f,0.0f,0.0f, 53, 0.003f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer PaddedCell = +{ + &Room, + "Padded Cell", + 0x0100, + true, + false, + {0, 1, 1.4f, 1.00f, -1000, -6000, 0, 0.17f, 0.10f, 1.0f, -1204, 0.001f, 0.0f,0.0f,0.0f, 207, 0.002f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Generic = +{ + &PaddedCell, + "Generic", + 0x0001, + true, + false, + {0, 0, 7.5f, 1.00f, -1000, -100, 0, 1.49f, 0.83f, 1.0f, -2602, 0.007f, 0.0f,0.0f,0.0f, 200, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f }, + false +}; + +static ReverbContainer Off = +{ + &Generic, + "Off", + 0x0000, + true, + false, + {0, 0, 7.5f, 1.00f, -10000, -10000, 0, 1.00f, 1.00f, 1.0f, -2602, 0.007f, 0.0f,0.0f,0.0f, 200, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 0.0f, 0.0f, 0x33f }, + false +}; + +ReverbContainer *DefaultEnvironments[26] = +{ + &Off, &PaddedCell, &Room, &Bathroom, &LivingRoom, &StoneRoom, &Auditorium, + &ConcertHall, &Cave, &Arena, &Hangar, &CarpettedHallway, &Hallway, &StoneCorridor, + &Alley, &Forest, &City, &Mountains, &Quarry, &Plain, &ParkingLot, &SewerPipe, + &Underwater, &Drugged, &Dizzy, &Psychotic +}; + +ReverbContainer *Environments = &Off; + +ReverbContainer *S_FindEnvironment (const char *name) +{ + ReverbContainer *probe = Environments; + + if (name == NULL) + return NULL; + + while (probe != NULL) + { + if (stricmp (probe->Name, name) == 0) + { + return probe; + } + probe = probe->Next; + } + return NULL; +} + +ReverbContainer *S_FindEnvironment (int id) +{ + ReverbContainer *probe = Environments; + + while (probe != NULL && probe->ID < id) + { + probe = probe->Next; + } + return (probe && probe->ID == id ? probe : NULL); +} + +void S_AddEnvironment (ReverbContainer *settings) +{ + ReverbContainer *probe = Environments; + ReverbContainer **ptr = &Environments; + + while (probe != NULL && probe->ID < settings->ID) + { + ptr = &probe->Next; + probe = probe->Next; + } + + if (probe != NULL && probe->ID == settings->ID) + { + // Built-in environments cannot be changed + if (!probe->Builtin) + { + settings->Next = probe->Next; + *ptr = settings; + delete[] const_cast(probe->Name); + delete probe; + } + } + else + { + settings->Next = probe; + *ptr = settings; + } +} + +void S_ReadReverbDef (FScanner &sc) +{ + const ReverbContainer *def; + ReverbContainer *newenv; + REVERB_PROPERTIES props; + char *name; + int id1, id2, i, j; + bool inited[NUM_REVERB_FIELDS]; + uint8_t bools[32]; + + while (sc.GetString ()) + { + name = strdup (sc.String); + sc.MustGetNumber (); + id1 = sc.Number; + sc.MustGetNumber (); + id2 = sc.Number; + sc.MustGetStringName ("{"); + memset (inited, 0, sizeof(inited)); + props.Instance = 0; + props.Flags = 0; + while (sc.MustGetString (), NUM_REVERB_FIELDS > (i = sc.MustMatchString (ReverbFieldNames))) + { + if (ReverbFields[i].Float) + { + sc.MustGetFloat (); + props.*ReverbFields[i].Float = (float)clamp (sc.Float, + double(ReverbFields[i].Min)/1000, + double(ReverbFields[i].Max)/1000); + } + else if (ReverbFields[i].Int) + { + sc.MustGetNumber (); + props.*ReverbFields[i].Int = (j = clamp (sc.Number, + ReverbFields[i].Min, ReverbFields[i].Max)); + if (i == 0 && j != sc.Number) + { + sc.ScriptError ("The Environment field is out of range."); + } + } + else + { + sc.MustGetString (); + bools[ReverbFields[i].Flag] = sc.MustMatchString (BoolNames); + } + inited[i] = true; + } + if (!inited[0]) + { + sc.ScriptError ("Sound %s is missing an Environment field.", name); + } + + // Add the new environment to the list, filling in uninitialized fields + // with values from the standard environment specified. + def = DefaultEnvironments[props.Environment]; + for (i = 0; i < NUM_REVERB_FIELDS; ++i) + { + if (ReverbFields[i].Float) + { + if (!inited[i]) + { + props.*ReverbFields[i].Float = def->Properties.*ReverbFields[i].Float; + } + } + else if (ReverbFields[i].Int) + { + if (!inited[i]) + { + props.*ReverbFields[i].Int = def->Properties.*ReverbFields[i].Int; + } + } + else + { + if (!inited[i]) + { + int mask = 1 << ReverbFields[i].Flag; + if (def->Properties.Flags & mask) + { + props.Flags |= mask; + } + } + else + { + if (bools[ReverbFields[i].Flag]) + { + props.Flags |= 1 << ReverbFields[i].Flag; + } + } + } + } + + newenv = new ReverbContainer; + newenv->Next = NULL; + newenv->Name = name; + newenv->ID = (id1 << 8) | id2; + newenv->Builtin = false; + newenv->Properties = props; + newenv->SoftwareWater = false; + S_AddEnvironment (newenv); + } +} + +void S_UnloadReverbDef () +{ + ReverbContainer *probe = Environments; + ReverbContainer **pNext = NULL; + + while (probe != NULL) + { + ReverbContainer *next = probe->Next; + if (!probe->Builtin) + { + if (pNext != NULL) *pNext = probe->Next; + free(const_cast(probe->Name)); + delete probe; + } + else + { + pNext = &probe->Next; + } + probe = next; + } + Environments = &Off; +} + diff --git a/source/common/sound/s_sound.cpp b/source/common/sound/s_sound.cpp new file mode 100644 index 000000000..af9bcb1de --- /dev/null +++ b/source/common/sound/s_sound.cpp @@ -0,0 +1,1804 @@ +/* +** s_sound.cpp +** Main sound engine +** +**--------------------------------------------------------------------------- +** Copyright 1998-2016 Randy Heit +** Copyright 2002-2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include + +#include "s_soundinternal.h" +#include "m_swap.h" +#include "superfasthash.h" +#include "c_cvars.h" + +#ifdef _WIN32 +#undef DrawText +#endif + +#ifdef DEFAULT_PITCH // undefine garbage from Windows.h +#undef DEFAULT_PITCH +#endif + +enum +{ + DEFAULT_PITCH = 128, +}; + +SoundEngine* soundEngine; +int sfx_empty = -1; + +//========================================================================== +// +// S_Init +// +//========================================================================== + +void SoundEngine::Init(TArray &curve) +{ + // Free all channels for use. + while (Channels != NULL) + { + ReturnChannel(Channels); + } + S_SoundCurve = std::move(curve); +} + +//========================================================================== +// +// SoundEngine::Clear +// +//========================================================================== + +void SoundEngine::Clear() +{ + StopAllChannels(); + UnloadAllSounds(); + GetSounds().Clear(); + ClearRandoms(); +} + +//========================================================================== +// +// S_Shutdown +// +//========================================================================== + +void SoundEngine::Shutdown () +{ + FSoundChan *chan, *next; + + StopAllChannels(); + + for (chan = FreeChannels; chan != NULL; chan = next) + { + next = chan->NextChan; + delete chan; + } + FreeChannels = NULL; +} + +//========================================================================== +// +// MarkUsed +// +//========================================================================== + +void SoundEngine::MarkUsed(int id) +{ + if ((unsigned)id < S_sfx.Size()) + { + S_sfx[id].bUsed = true; + } +} + +//========================================================================== +// +// Cache all marked sounds +// +//========================================================================== + +void SoundEngine::CacheMarkedSounds() +{ + // Don't unload sounds that are playing right now. + for (FSoundChan* chan = Channels; chan != nullptr; chan = chan->NextChan) + { + MarkUsed(chan->SoundID); + } + + for (unsigned i = 1; i < S_sfx.Size(); ++i) + { + if (S_sfx[i].bUsed) + { + CacheSound(&S_sfx[i]); + } + } + for (unsigned i = 1; i < S_sfx.Size(); ++i) + { + if (!S_sfx[i].bUsed && S_sfx[i].link == sfxinfo_t::NO_LINK) + { + UnloadSound(&S_sfx[i]); + } + } +} + +//========================================================================== +// +// S_CacheSound +// +//========================================================================== + +void SoundEngine::CacheSound (sfxinfo_t *sfx) +{ + if (GSnd && !sfx->bTentative) + { + sfxinfo_t *orig = sfx; + while (!sfx->bRandomHeader && sfx->link != sfxinfo_t::NO_LINK) + { + sfx = &S_sfx[sfx->link]; + } + if (sfx->bRandomHeader) + { + CacheRandomSound(sfx); + } + else + { + // Since we do not know in what format the sound will be used, we have to cache both. + FSoundLoadBuffer SoundBuffer; + LoadSound(sfx, &SoundBuffer); + LoadSound3D(sfx, &SoundBuffer); + sfx->bUsed = true; + } + } +} + +//========================================================================== +// +// S_UnloadSound +// +//========================================================================== + +void SoundEngine::UnloadSound (sfxinfo_t *sfx) +{ + if (sfx->data3d.isValid() && sfx->data != sfx->data3d) + GSnd->UnloadSound(sfx->data3d); + if (sfx->data.isValid()) + GSnd->UnloadSound(sfx->data); + sfx->data.Clear(); + sfx->data3d.Clear(); +} + +//========================================================================== +// +// S_GetChannel +// +// Returns a free channel for the system sound interface. +// +//========================================================================== + +FSoundChan *SoundEngine::GetChannel(void *syschan) +{ + FSoundChan *chan; + + if (FreeChannels != NULL) + { + chan = FreeChannels; + UnlinkChannel(chan); + } + else + { + chan = new FSoundChan; + memset(chan, 0, sizeof(*chan)); + } + LinkChannel(chan, &Channels); + chan->SysChannel = syschan; + return chan; +} + +//========================================================================== +// +// S_ReturnChannel +// +// Returns a channel to the free pool. +// +//========================================================================== + +void SoundEngine::ReturnChannel(FSoundChan *chan) +{ + UnlinkChannel(chan); + memset(chan, 0, sizeof(*chan)); + LinkChannel(chan, &FreeChannels); +} + +//========================================================================== +// +// S_UnlinkChannel +// +//========================================================================== + +void SoundEngine::UnlinkChannel(FSoundChan *chan) +{ + *(chan->PrevChan) = chan->NextChan; + if (chan->NextChan != NULL) + { + chan->NextChan->PrevChan = chan->PrevChan; + } +} + +//========================================================================== +// +// S_LinkChannel +// +//========================================================================== + +void SoundEngine::LinkChannel(FSoundChan *chan, FSoundChan **head) +{ + chan->NextChan = *head; + if (chan->NextChan != NULL) + { + chan->NextChan->PrevChan = &chan->NextChan; + } + *head = chan; + chan->PrevChan = head; +} + +//========================================================================== +// +// +// +//========================================================================== + +TArray SoundEngine::AllActiveChannels() +{ + TArray chans; + + for (auto chan = Channels; chan != nullptr; chan = chan->NextChan) + { + // If the sound is forgettable, this is as good a time as + // any to forget about it. And if it's a UI sound, it shouldn't + // be stored in the savegame. + if (!(chan->ChanFlags & (CHANF_FORGETTABLE | CHANF_UI))) + { + chans.Push(chan); + } + } + return chans; +} + +//========================================================================== +// +// +// +//========================================================================== + +FString SoundEngine::ListSoundChannels() +{ + FString output; + FSoundChan* chan; + int count = 0; + for (chan = Channels; chan != nullptr; chan = chan->NextChan) + { + if (!(chan->ChanFlags & CHANF_EVICTED)) + { + FVector3 chanorigin; + + CalcPosVel(chan, &chanorigin, nullptr); + + output.AppendFormat("%s at (%1.5f, %1.5f, %1.5f)\n", (const char*)S_sfx[chan->SoundID].name.GetChars(), chanorigin.X, chanorigin.Y, chanorigin.Z); + count++; + } + } + output.AppendFormat("%d sounds playing\n", count); + return output; +} + +// [RH] Split S_StartSoundAtVolume into multiple parts so that sounds can +// be specified both by id and by name. Also borrowed some stuff from +// Hexen and parameters from Quake. + +//========================================================================== +// +// CalcPosVel +// +// Retrieves a sound's position and velocity for 3D sounds. This version +// is for an already playing sound. +// +//========================================================================= + +void SoundEngine::CalcPosVel(FSoundChan *chan, FVector3 *pos, FVector3 *vel) +{ + CalcPosVel(chan->SourceType, chan->Source, chan->Point, chan->EntChannel, chan->ChanFlags, chan->OrgID, pos, vel, chan); +} + +bool SoundEngine::ValidatePosVel(const FSoundChan* const chan, const FVector3& pos, const FVector3& vel) +{ + return ValidatePosVel(chan->SourceType, chan->Source, pos, vel); +} + +//========================================================================== +// +// +// +//========================================================================== + +FSoundID SoundEngine::ResolveSound(const void *, int, FSoundID soundid, float &attenuation) +{ + const sfxinfo_t &sfx = S_sfx[soundid]; + + if (sfx.bRandomHeader) + { + // Random sounds attenuate based on the original (random) sound as well as the chosen one. + attenuation *= sfx.Attenuation; + return PickReplacement (soundid); + } + else + { + return sfx.link; + } +} + +//========================================================================== +// +// S_StartSound +// +// 0 attenuation means full volume over whole primaryLevel-> +// 0 < attenuation means to scale the distance by that amount when +// calculating volume. +// +//========================================================================== + +FSoundChan *SoundEngine::StartSound(int type, const void *source, + const FVector3 *pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, + FRolloffInfo *forcedrolloff, float spitch) +{ + sfxinfo_t *sfx; + EChanFlags chanflags = flags; + int basepriority; + int org_id; + int pitch; + FSoundChan *chan; + FVector3 pos, vel; + FRolloffInfo *rolloff; + FSoundLoadBuffer SoundBuffer; + + if (sound_id <= 0 || volume <= 0 || nosfx || nosound ) + return NULL; + + // prevent crashes. + if (type == SOURCE_Unattached && pt == nullptr) type = SOURCE_None; + + org_id = sound_id; + + CalcPosVel(type, source, &pt->X, channel, chanflags, sound_id, &pos, &vel, nullptr); + + if (!ValidatePosVel(type, source, pos, vel)) + { + return nullptr; + } + + sfx = &S_sfx[sound_id]; + + // Scale volume according to SNDINFO data. + volume = std::min(volume * sfx->Volume, 1.f); + if (volume <= 0) + return NULL; + + // When resolving a link we do not want to get the NearLimit of + // the referenced sound so some additional checks are required + int near_limit = sfx->NearLimit; + float limit_range = sfx->LimitRange; + auto pitchmask = sfx->PitchMask; + rolloff = &sfx->Rolloff; + + // Resolve player sounds, random sounds, and aliases + while (sfx->link != sfxinfo_t::NO_LINK) + { + sound_id = ResolveSound(source, type, sound_id, attenuation); + if (sound_id < 0) return nullptr; + auto newsfx = &S_sfx[sound_id]; + if (newsfx != sfx) + { + if (near_limit < 0) + { + near_limit = newsfx->NearLimit; + limit_range = newsfx->LimitRange; + } + if (rolloff->MinDistance == 0) + { + rolloff = &newsfx->Rolloff; + } + sfx = newsfx; + } + else return nullptr; // nothing got replaced, prevent an endless loop, + + } + + // Attenuate the attenuation based on the sound. + attenuation *= sfx->Attenuation; + + // The passed rolloff overrides any sound-specific rolloff. + if (forcedrolloff != NULL && forcedrolloff->MinDistance != 0) + { + rolloff = forcedrolloff; + } + + // If no valid rolloff was set, use the global default. + if (rolloff->MinDistance == 0) + { + rolloff = &S_Rolloff; + } + + // If this is a singular sound, don't play it if it's already playing. + if (sfx->bSingular && CheckSingular(sound_id)) + { + chanflags |= CHANF_EVICTED; + } + + // If the sound is unpositioned or comes from the listener, it is + // never limited. + if (type == SOURCE_None || source == listener.ListenerObject) + { + near_limit = 0; + } + + // If this sound doesn't like playing near itself, don't play it if + // that's what would happen. (Does this really need the SOURCE_Actor restriction?) + if (near_limit > 0 && CheckSoundLimit(sfx, pos, near_limit, limit_range, type, type == SOURCE_Actor? source : nullptr, channel)) + { + chanflags |= CHANF_EVICTED; + } + + // If the sound is blocked and not looped, return now. If the sound + // is blocked and looped, pretend to play it so that it can + // eventually play for real. + if ((chanflags & (CHANF_EVICTED | CHANF_LOOP)) == CHANF_EVICTED) + { + return NULL; + } + + // Make sure the sound is loaded. + sfx = LoadSound(sfx, &SoundBuffer); + + // The empty sound never plays. + if (sfx->lumpnum == sfx_empty) + { + return NULL; + } + + // Select priority. + if (type == SOURCE_None || source == listener.ListenerObject) + { + basepriority = 80; + } + else + { + basepriority = 0; + } + + int seen = 0; + if (source != NULL && channel == CHAN_AUTO) + { + // Select a channel that isn't already playing something. + // Try channel 0 first, then travel from channel 7 down. + if (!IsChannelUsed(type, source, 0, &seen)) + { + channel = 0; + } + else + { + for (channel = 7; channel > 0; --channel) + { + if (!IsChannelUsed(type, source, channel, &seen)) + { + break; + } + } + if (channel == 0) + { // Crap. No free channels. + return NULL; + } + } + } + + // If this actor is already playing something on the selected channel, stop it. + if (!(chanflags & CHANF_OVERLAP) && type != SOURCE_None && ((source == NULL && channel != CHAN_AUTO) || (source != NULL && IsChannelUsed(type, source, channel, &seen)))) + { + for (chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->SourceType == type && chan->EntChannel == channel) + { + const bool foundit = (type == SOURCE_Unattached) + ? (chan->Point[0] == pt->X && chan->Point[2] == pt->Z && chan->Point[1] == pt->Y) + : (chan->Source == source); + + if (foundit) + { + StopChannel(chan); + break; + } + } + } + } + + // sound is paused and a non-looped sound is being started. + // Such a sound would play right after unpausing which wouldn't sound right. + if (!(chanflags & CHANF_LOOP) && !(chanflags & (CHANF_UI|CHANF_NOPAUSE)) && SoundPaused) + { + return NULL; + } + + // Vary the sfx pitches. + if (pitchmask != 0) + { + pitch = DEFAULT_PITCH - (rand() & pitchmask) + (rand() & pitchmask); + } + else + { + pitch = DEFAULT_PITCH; + } + + if (chanflags & CHANF_EVICTED) + { + chan = NULL; + } + else + { + int startflags = 0; + if (chanflags & CHANF_LOOP) startflags |= SNDF_LOOP; + if (chanflags & CHANF_AREA) startflags |= SNDF_AREA; + if (chanflags & (CHANF_UI|CHANF_NOPAUSE)) startflags |= SNDF_NOPAUSE; + if (chanflags & CHANF_UI) startflags |= SNDF_NOREVERB; + + if (attenuation > 0 && type != SOURCE_None) + { + LoadSound3D(sfx, &SoundBuffer); + chan = (FSoundChan*)GSnd->StartSound3D (sfx->data3d, &listener, float(volume), rolloff, float(attenuation), pitch, basepriority, pos, vel, channel, startflags, NULL); + } + else + { + chan = (FSoundChan*)GSnd->StartSound (sfx->data, float(volume), pitch, startflags, NULL); + } + } + if (chan == NULL && (chanflags & CHANF_LOOP)) + { + chan = (FSoundChan*)GetChannel(NULL); + GSnd->MarkStartTime(chan); + chanflags |= CHANF_EVICTED; + } + if (attenuation > 0) + { + chanflags |= CHANF_IS3D | CHANF_JUSTSTARTED; + } + else + { + chanflags |= CHANF_LISTENERZ | CHANF_JUSTSTARTED; + } + if (chan != NULL) + { + chan->SoundID = sound_id; + chan->OrgID = FSoundID(org_id); + chan->EntChannel = channel; + chan->Volume = float(volume); + chan->ChanFlags |= chanflags; + chan->NearLimit = near_limit; + chan->LimitRange = limit_range; + chan->Pitch = pitch; + chan->Priority = basepriority; + chan->DistanceScale = float(attenuation); + chan->SourceType = type; + if (type == SOURCE_Unattached) + { + chan->Point[0] = pt->X; chan->Point[1] = pt->Y; chan->Point[2] = pt->Z; + } + else if (type != SOURCE_None) + { + chan->Source = source; + } + + if (spitch > 0.0) + SetPitch(chan, spitch); + } + + return chan; +} + +//========================================================================== +// +// S_RestartSound +// +// Attempts to restart looping sounds that were evicted from their channels. +// +//========================================================================== + +void SoundEngine::RestartChannel(FSoundChan *chan) +{ + assert(chan->ChanFlags & CHANF_EVICTED); + + FSoundChan *ochan; + sfxinfo_t *sfx = &S_sfx[chan->SoundID]; + FSoundLoadBuffer SoundBuffer; + + // If this is a singular sound, don't play it if it's already playing. + if (sfx->bSingular && CheckSingular(chan->SoundID)) + return; + + sfx = LoadSound(sfx, &SoundBuffer); + + // The empty sound never plays. + if (sfx->lumpnum == sfx_empty) + { + return; + } + + EChanFlags oldflags = chan->ChanFlags; + + int startflags = 0; + if (chan->ChanFlags & CHANF_LOOP) startflags |= SNDF_LOOP; + if (chan->ChanFlags & CHANF_AREA) startflags |= SNDF_AREA; + if (chan->ChanFlags & (CHANF_UI|CHANF_NOPAUSE)) startflags |= SNDF_NOPAUSE; + if (chan->ChanFlags & CHANF_ABSTIME) startflags |= SNDF_ABSTIME; + + if (chan->ChanFlags & CHANF_IS3D) + { + FVector3 pos, vel; + + CalcPosVel(chan, &pos, &vel); + + if (!ValidatePosVel(chan, pos, vel)) + { + return; + } + + // If this sound doesn't like playing near itself, don't play it if + // that's what would happen. + if (chan->NearLimit > 0 && CheckSoundLimit(&S_sfx[chan->SoundID], pos, chan->NearLimit, chan->LimitRange, 0, NULL, 0)) + { + return; + } + + LoadSound3D(sfx, &SoundBuffer); + chan->ChanFlags &= ~(CHANF_EVICTED|CHANF_ABSTIME); + ochan = (FSoundChan*)GSnd->StartSound3D(sfx->data3d, &listener, chan->Volume, &chan->Rolloff, chan->DistanceScale, chan->Pitch, + chan->Priority, pos, vel, chan->EntChannel, startflags, chan); + } + else + { + chan->ChanFlags &= ~(CHANF_EVICTED|CHANF_ABSTIME); + ochan = (FSoundChan*)GSnd->StartSound(sfx->data, chan->Volume, chan->Pitch, startflags, chan); + } + assert(ochan == NULL || ochan == chan); + if (ochan == NULL) + { + chan->ChanFlags = oldflags; + } +} + +//========================================================================== +// +// S_LoadSound +// +// Returns a pointer to the sfxinfo with the actual sound data. +// +//========================================================================== + +sfxinfo_t *SoundEngine::LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer) +{ + if (GSnd->IsNull()) return sfx; + + while (!sfx->data.isValid()) + { + unsigned int i; + + // If the sound doesn't exist, replace it with the empty sound. + if (sfx->lumpnum == -1) + { + sfx->lumpnum = sfx_empty; + } + + // See if there is another sound already initialized with this lump. If so, + // then set this one up as a link, and don't load the sound again. + for (i = 0; i < S_sfx.Size(); i++) + { + if (S_sfx[i].data.isValid() && S_sfx[i].link == sfxinfo_t::NO_LINK && S_sfx[i].lumpnum == sfx->lumpnum && + (!sfx->bLoadRAW || (sfx->RawRate == S_sfx[i].RawRate))) // Raw sounds with different sample rates may not share buffers, even if they use the same source data. + { + //DPrintf (DMSG_NOTIFY, "Linked %s to %s (%d)\n", sfx->name.GetChars(), S_sfx[i].name.GetChars(), i); + sfx->link = i; + // This is necessary to avoid using the rolloff settings of the linked sound if its + // settings are different. + if (sfx->Rolloff.MinDistance == 0) sfx->Rolloff = S_Rolloff; + return &S_sfx[i]; + } + } + + //DPrintf(DMSG_NOTIFY, "Loading sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); + + auto sfxdata = ReadSound(sfx->lumpnum); + int size = sfxdata.Size(); + if (size > 8) + { + int32_t dmxlen = LittleLong(((int32_t *)sfxdata.Data())[1]); + std::pair snd; + + // If the sound is voc, use the custom loader. + if (strncmp ((const char *)sfxdata.Data(), "Creative Voice File", 19) == 0) + { + snd = GSnd->LoadSoundVoc(sfxdata.Data(), size); + } + // If the sound is raw, just load it as such. + else if (sfx->bLoadRAW) + { + snd = GSnd->LoadSoundRaw(sfxdata.Data(), size, sfx->RawRate, 1, 8, sfx->LoopStart); + } + // Otherwise, try the sound as DMX format. + else if (((uint8_t *)sfxdata.Data())[0] == 3 && ((uint8_t *)sfxdata.Data())[1] == 0 && dmxlen <= size - 8) + { + int frequency = LittleShort(((uint16_t *)sfxdata.Data())[1]); + if (frequency == 0) frequency = 11025; + snd = GSnd->LoadSoundRaw(sfxdata.Data()+8, dmxlen, frequency, 1, 8, sfx->LoopStart); + } + // If that fails, let the sound system try and figure it out. + else + { + snd = GSnd->LoadSound(sfxdata.Data(), size, false, pBuffer); + } + + sfx->data = snd.first; + if(snd.second) + sfx->data3d = sfx->data; + } + + if (!sfx->data.isValid()) + { + if (sfx->lumpnum != sfx_empty) + { + sfx->lumpnum = sfx_empty; + continue; + } + } + break; + } + return sfx; +} + +void SoundEngine::LoadSound3D(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer) +{ + if (GSnd->IsNull()) return; + + if(sfx->data3d.isValid()) + return; + + //DPrintf(DMSG_NOTIFY, "Loading monoized sound \"%s\" (%td)\n", sfx->name.GetChars(), sfx - &S_sfx[0]); + + std::pair snd; + + if (pBuffer->mBuffer.size() > 0) + { + snd = GSnd->LoadSoundBuffered(pBuffer, true); + } + else if (sfx->lumpnum >= 0) + { + auto sfxdata = ReadSound(sfx->lumpnum); + int size = sfxdata.Size(); + if (size <= 8) return; + int32_t dmxlen = LittleLong(((int32_t *)sfxdata.Data())[1]); + + // If the sound is voc, use the custom loader. + if (strncmp((const char *)sfxdata.Data(), "Creative Voice File", 19) == 0) + { + snd = GSnd->LoadSoundVoc(sfxdata.Data(), size, true); + } + // If the sound is raw, just load it as such. + else if (sfx->bLoadRAW) + { + snd = GSnd->LoadSoundRaw(sfxdata.Data(), size, sfx->RawRate, 1, 8, sfx->LoopStart, true); + } + // Otherwise, try the sound as DMX format. + else if (((uint8_t *)sfxdata.Data())[0] == 3 && ((uint8_t *)sfxdata.Data())[1] == 0 && dmxlen <= size - 8) + { + int frequency = LittleShort(((uint16_t *)sfxdata.Data())[1]); + if (frequency == 0) frequency = 11025; + snd = GSnd->LoadSoundRaw(sfxdata.Data() + 8, dmxlen, frequency, 1, 8, sfx->LoopStart, -1, true); + } + // If that fails, let the sound system try and figure it out. + else + { + snd = GSnd->LoadSound(sfxdata.Data(), size, true, pBuffer); + } + } + + sfx->data3d = snd.first; +} + +//========================================================================== +// +// S_CheckSingular +// +// Returns true if a copy of this sound is already playing. +// +//========================================================================== + +bool SoundEngine::CheckSingular(int sound_id) +{ + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->OrgID == sound_id) + { + return true; + } + } + return false; +} + +//========================================================================== +// +// S_CheckSoundLimit +// +// Limits the number of nearby copies of a sound that can play near +// each other. If there are NearLimit instances of this sound already +// playing within sqrt(limit_range) (typically 256 units) of the new sound, the +// new sound will not start. +// +// If an actor is specified, and it is already playing the same sound on +// the same channel, this sound will not be limited. In this case, we're +// restarting an already playing sound, so there's no need to limit it. +// +// Returns true if the sound should not play. +// +//========================================================================== + +bool SoundEngine::CheckSoundLimit(sfxinfo_t *sfx, const FVector3 &pos, int near_limit, float limit_range, + int sourcetype, const void *actor, int channel) +{ + FSoundChan *chan; + int count; + + for (chan = Channels, count = 0; chan != NULL && count < near_limit; chan = chan->NextChan) + { + if (!(chan->ChanFlags & CHANF_EVICTED) && &S_sfx[chan->SoundID] == sfx) + { + FVector3 chanorigin; + + if (actor != NULL && chan->EntChannel == channel && + chan->SourceType == sourcetype && chan->Source == actor) + { // We are restarting a playing sound. Always let it play. + return false; + } + + CalcPosVel(chan, &chanorigin, NULL); + if ((chanorigin - pos).LengthSquared() <= limit_range) + { + count++; + } + } + } + return count >= near_limit; +} + +//========================================================================== +// +// S_StopSound +// +// Stops an unpositioned sound from playing on a specific channel. +// +//========================================================================== + +void SoundEngine::StopSoundID(int sound_id) +{ + FSoundChan* chan = Channels; + while (chan != NULL) + { + FSoundChan* next = chan->NextChan; + if (sound_id == chan->OrgID) + { + StopChannel(chan); + } + chan = next; + } +} + +//========================================================================== +// +// S_StopSound +// +// Stops an unpositioned sound from playing on a specific channel. +// +//========================================================================== + +void SoundEngine::StopSound (int channel, int sound_id) +{ + FSoundChan *chan = Channels; + while (chan != NULL) + { + FSoundChan *next = chan->NextChan; + if ((chan->SourceType == SOURCE_None && (sound_id == -1 || sound_id == chan->OrgID)) && (channel == CHAN_AUTO || channel == chan->EntChannel)) + { + StopChannel(chan); + } + chan = next; + } +} + +//========================================================================== +// +// S_StopSound +// +// Stops a sound from a single actor from playing on a specific channel. +// +//========================================================================== + +void SoundEngine::StopSound(int sourcetype, const void* actor, int channel, int sound_id) +{ + FSoundChan* chan = Channels; + while (chan != NULL) + { + FSoundChan* next = chan->NextChan; + if (chan->SourceType == sourcetype && + chan->Source == actor && + (sound_id == -1? (chan->EntChannel == channel || channel < 0) : (chan->OrgID == sound_id))) + { + StopChannel(chan); + } + chan = next; + } +} + +//========================================================================== +// +// S_StopAllChannels +// +//========================================================================== + +void SoundEngine::StopAllChannels () +{ + FSoundChan *chan = Channels; + while (chan != NULL) + { + FSoundChan *next = chan->NextChan; + StopChannel(chan); + chan = next; + } + + if (GSnd) + GSnd->UpdateSounds(); +} + +//========================================================================== +// +// S_RelinkSound +// +// Moves all the sounds from one thing to another. If the destination is +// NULL, then the sound becomes a positioned sound. +//========================================================================== + +void SoundEngine::RelinkSound (int sourcetype, const void *from, const void *to, const FVector3 *optpos) +{ + if (from == NULL) + return; + + FSoundChan *chan = Channels; + while (chan != NULL) + { + FSoundChan *next = chan->NextChan; + if (chan->SourceType == sourcetype && chan->Source == from) + { + if (to != NULL) + { + chan->Source = to; + } + else if (!(chan->ChanFlags & CHANF_LOOP) && optpos) + { + chan->Source = NULL; + chan->SourceType = SOURCE_Unattached; + chan->Point[0] = optpos->X; + chan->Point[1] = optpos->Y; + chan->Point[2] = optpos->Z; + } + else + { + StopChannel(chan); + } + } + chan = next; + } +} + + +//========================================================================== +// +// S_ChangeSoundVolume +// +//========================================================================== + +void SoundEngine::ChangeSoundVolume(int sourcetype, const void *source, int channel, double dvolume) +{ + float volume = float(dvolume); + // don't let volume get out of bounds + if (volume < 0.0) + volume = 0.0; + else if (volume > 1.0) + volume = 1.0; + + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->SourceType == sourcetype && + chan->Source == source && + (chan->EntChannel == channel || channel == -1)) + { + GSnd->ChannelVolume(chan, volume); + chan->Volume = volume; + return; + } + } + return; +} + +void SoundEngine::SetVolume(FSoundChan* chan, float volume) +{ + if (volume < 0.0) volume = 0.0; + else if (volume > 1.0) volume = 1.0; + + assert(chan != nullptr); + GSnd->ChannelVolume(chan, volume); + chan->Volume = volume; +} + +//========================================================================== +// +// S_ChangeSoundPitch +// +//========================================================================== + +void SoundEngine::ChangeSoundPitch(int sourcetype, const void *source, int channel, double pitch, int sound_id) +{ + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->SourceType == sourcetype && + chan->Source == source && + (sound_id == -1? (chan->EntChannel == channel) : (chan->OrgID == sound_id))) + { + SetPitch(chan, (float)pitch); + return; + } + } + return; +} + +void SoundEngine::SetPitch(FSoundChan *chan, float pitch) +{ + assert(chan != nullptr); + GSnd->ChannelPitch(chan, std::max(0.0001f, pitch)); + chan->Pitch = std::max(1, int(float(DEFAULT_PITCH) * pitch)); +} + +//========================================================================== +// +// S_GetSoundPlayingInfo +// +// Is a sound being played by a specific emitter? +//========================================================================== + +int SoundEngine::GetSoundPlayingInfo (int sourcetype, const void *source, int sound_id) +{ + int count = 0; + if (sound_id > 0) + { + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->OrgID == sound_id && (sourcetype == SOURCE_Any || + (chan->SourceType == sourcetype && + chan->Source == source))) + { + count++; + } + } + } + return count; +} + +//========================================================================== +// +// S_IsChannelUsed +// +// Returns true if the channel is in use. Also fills in a bitmask of +// channels seen while scanning for this one, to make searching for unused +// channels faster. Initialize seen to 0 for the first call. +// +//========================================================================== + +bool SoundEngine::IsChannelUsed(int sourcetype, const void *actor, int channel, int *seen) +{ + if (*seen & (1 << channel)) + { + return true; + } + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->SourceType == sourcetype && chan->Source == actor) + { + *seen |= 1 << chan->EntChannel; + if (chan->EntChannel == channel) + { + return true; + } + } + } + return false; +} + +//========================================================================== +// +// S_IsActorPlayingSomething +// +//========================================================================== + +bool SoundEngine::IsSourcePlayingSomething (int sourcetype, const void *actor, int channel, int sound_id) +{ + for (FSoundChan *chan = Channels; chan != NULL; chan = chan->NextChan) + { + if (chan->SourceType == sourcetype && (sourcetype == SOURCE_None || sourcetype == SOURCE_Unattached || chan->Source == actor)) + { + if ((channel == 0 || chan->EntChannel == channel) && (sound_id <= 0 || chan->OrgID == sound_id)) + { + return true; + } + } + } + return false; +} + +//========================================================================== +// +// S_EvictAllChannels +// +// Forcibly evicts all channels so that there are none playing, but all +// information needed to restart them is retained. +// +//========================================================================== + +void SoundEngine::EvictAllChannels() +{ + FSoundChan *chan, *next; + + for (chan = Channels; chan != NULL; chan = next) + { + next = chan->NextChan; + + if (!(chan->ChanFlags & CHANF_EVICTED)) + { + chan->ChanFlags |= CHANF_EVICTED; + if (chan->SysChannel != NULL) + { + if (!(chan->ChanFlags & CHANF_ABSTIME)) + { + chan->StartTime = GSnd ? GSnd->GetPosition(chan) : 0; + chan->ChanFlags |= CHANF_ABSTIME; + } + StopChannel(chan); + } +// assert(chan->NextChan == next); + } + } +} + +//========================================================================== +// +// S_RestoreEvictedChannel +// +// Recursive helper for S_RestoreEvictedChannels(). +// +//========================================================================== + +void SoundEngine::RestoreEvictedChannel(FSoundChan *chan) +{ + if (chan == NULL) + { + return; + } + RestoreEvictedChannel(chan->NextChan); + if (chan->ChanFlags & CHANF_EVICTED) + { + RestartChannel(chan); + if (!(chan->ChanFlags & CHANF_LOOP)) + { + if (chan->ChanFlags & CHANF_EVICTED) + { // Still evicted and not looping? Forget about it. + ReturnChannel(chan); + } + else if (!(chan->ChanFlags & CHANF_JUSTSTARTED)) + { // Should this sound become evicted again, it's okay to forget about it. + chan->ChanFlags |= CHANF_FORGETTABLE; + } + } + } + else if (chan->SysChannel == NULL && (chan->ChanFlags & (CHANF_FORGETTABLE | CHANF_LOOP)) == CHANF_FORGETTABLE) + { + ReturnChannel(chan); + } +} + +//========================================================================== +// +// S_RestoreEvictedChannels +// +// Restarts as many evicted channels as possible. Any channels that could +// not be started and are not looping are moved to the free pool. +// +//========================================================================== + +void SoundEngine::RestoreEvictedChannels() +{ + // Restart channels in the same order they were originally played. + RestoreEvictedChannel(Channels); +} + +//========================================================================== +// +// S_UpdateSounds +// +// Updates music & sounds +//========================================================================== + +void SoundEngine::UpdateSounds(int time) +{ + FVector3 pos, vel; + + for (FSoundChan* chan = Channels; chan != NULL; chan = chan->NextChan) + { + if ((chan->ChanFlags & (CHANF_EVICTED | CHANF_IS3D)) == CHANF_IS3D) + { + CalcPosVel(chan, &pos, &vel); + + if (ValidatePosVel(chan, pos, vel)) + { + GSnd->UpdateSoundParams3D(&listener, chan, !!(chan->ChanFlags & CHANF_AREA), pos, vel); + } + } + chan->ChanFlags &= ~CHANF_JUSTSTARTED; + } + + GSnd->UpdateListener(&listener); + GSnd->UpdateSounds(); + + if (time >= RestartEvictionsAt) + { + RestartEvictionsAt = 0; + RestoreEvictedChannels(); + } +} + +//========================================================================== +// +// S_GetRolloff +// +//========================================================================== + +float SoundEngine::GetRolloff(const FRolloffInfo* rolloff, float distance) +{ + if (rolloff == NULL) + { + return 0; + } + if (distance <= rolloff->MinDistance) + { + return 1.f; + } + // Logarithmic rolloff has no max distance where it goes silent. + if (rolloff->RolloffType == ROLLOFF_Log) + { + return rolloff->MinDistance / (rolloff->MinDistance + rolloff->RolloffFactor * (distance - rolloff->MinDistance)); + } + if (distance >= rolloff->MaxDistance) + { + return 0.f; + } + + float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance); + if (rolloff->RolloffType == ROLLOFF_Linear) + { + return volume; + } + + if (rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve.Size() > 0) + { + return S_SoundCurve[int(S_SoundCurve.Size() * (1.f - volume))] / 127.f; + } + return (powf(10.f, volume) - 1.f) / 9.f; +} + +//========================================================================== +// +// S_ChannelEnded (callback for sound interface code) +// +//========================================================================== + +void SoundEngine::ChannelEnded(FISoundChannel *ichan) +{ + FSoundChan *schan = static_cast(ichan); + bool evicted; + + if (schan != NULL) + { + // If the sound was stopped with GSnd->StopSound(), then we know + // it wasn't evicted. Otherwise, if it's looping, it must have + // been evicted. If it's not looping, then it was evicted if it + // didn't reach the end of its playback. + if (schan->ChanFlags & CHANF_FORGETTABLE) + { + evicted = false; + } + else if (schan->ChanFlags & (CHANF_LOOP | CHANF_EVICTED)) + { + evicted = true; + } + else + { + unsigned int pos = GSnd->GetPosition(schan); + unsigned int len = GSnd->GetSampleLength(S_sfx[schan->SoundID].data); + if (pos == 0) + { + evicted = !!(schan->ChanFlags & CHANF_JUSTSTARTED); + } + else + { + evicted = (pos < len); + } + } + if (!evicted) + { + ReturnChannel(schan); + } + else + { + schan->ChanFlags |= CHANF_EVICTED; + schan->SysChannel = NULL; + } + } +} + +//========================================================================== +// +// S_ChannelVirtualChanged (callback for sound interface code) +// +//========================================================================== + +void SoundEngine::ChannelVirtualChanged(FISoundChannel *ichan, bool is_virtual) +{ + FSoundChan *schan = static_cast(ichan); + if (is_virtual) + { + schan->ChanFlags |= CHANF_VIRTUAL; + } + else + { + schan->ChanFlags &= ~CHANF_VIRTUAL; + } +} + +//========================================================================== +// +// StopChannel +// +//========================================================================== + +void SoundEngine::StopChannel(FSoundChan *chan) +{ + if (chan == NULL) + return; + + if (chan->SysChannel != NULL) + { + // S_EvictAllChannels() will set the CHAN_EVICTED flag to indicate + // that it wants to keep all the channel information around. + if (!(chan->ChanFlags & CHANF_EVICTED)) + { + chan->ChanFlags |= CHANF_FORGETTABLE; + if (chan->SourceType == SOURCE_Actor) + { + chan->Source = NULL; + } + } + GSnd->StopChannel(chan); + } + else + { + ReturnChannel(chan); + } +} + +void SoundEngine::UnloadAllSounds() +{ + for (unsigned i = 0; i < S_sfx.Size(); i++) + { + UnloadSound(&S_sfx[i]); + } +} + +void SoundEngine::Reset() +{ + EvictAllChannels(); + I_CloseSound(); + I_InitSound(); + RestoreEvictedChannels(); +} + + +//========================================================================== +// +// S_FindSound +// +// Given a logical name, find the sound's index in S_sfx. +//========================================================================== + +int SoundEngine::FindSound(const char* logicalname) +{ + int i; + + if (logicalname != NULL) + { + i = S_sfx[MakeKey(logicalname) % S_sfx.Size()].index; + + while ((i != 0) && stricmp(S_sfx[i].name, logicalname)) + i = S_sfx[i].next; + + return i; + } + else + { + return 0; + } +} + +int SoundEngine::FindSoundByResID(int resid) +{ + auto p = ResIdMap.CheckKey(resid); + return p ? *p : 0; +} + +//========================================================================== +// +// S_FindSoundNoHash +// +// Given a logical name, find the sound's index in S_sfx without +// using the hash table. +//========================================================================== + +int SoundEngine::FindSoundNoHash(const char* logicalname) +{ + unsigned int i; + + for (i = 1; i < S_sfx.Size(); i++) + { + if (stricmp(S_sfx[i].name, logicalname) == 0) + { + return i; + } + } + return 0; +} + +//========================================================================== +// +// S_FindSoundByLump +// +// Given a sound lump, find the sound's index in S_sfx. +//========================================================================== + +int SoundEngine::FindSoundByLump(int lump) +{ + if (lump != -1) + { + unsigned int i; + + for (i = 1; i < S_sfx.Size(); i++) + if (S_sfx[i].lumpnum == lump) + return i; + } + return 0; +} + +//========================================================================== +// +// S_AddSoundLump +// +// Adds a new sound mapping to S_sfx. +//========================================================================== + +int SoundEngine::AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid, int nearlimit) +{ + S_sfx.Reserve(1); + sfxinfo_t &newsfx = S_sfx.Last(); + + newsfx.data.Clear(); + newsfx.data3d.Clear(); + newsfx.name = logicalname; + newsfx.lumpnum = lump; + newsfx.next = 0; + newsfx.index = 0; + newsfx.Volume = 1; + newsfx.Attenuation = 1; + newsfx.PitchMask = CurrentPitchMask; + newsfx.NearLimit = nearlimit; + newsfx.LimitRange = 256 * 256; + newsfx.bRandomHeader = false; + newsfx.bLoadRAW = false; + newsfx.b16bit = false; + newsfx.bUsed = false; + newsfx.bSingular = false; + newsfx.bTentative = false; + newsfx.ResourceId = resid; + newsfx.RawRate = 0; + newsfx.link = sfxinfo_t::NO_LINK; + newsfx.Rolloff.RolloffType = ROLLOFF_Doom; + newsfx.Rolloff.MinDistance = 0; + newsfx.Rolloff.MaxDistance = 0; + newsfx.LoopStart = -1; + + if (resid >= 0) ResIdMap[resid] = S_sfx.Size() - 1; + return (int)S_sfx.Size()-1; +} + +int SoundEngine::AddSfx(sfxinfo_t &sfx) +{ + S_sfx.Push(sfx); + if (sfx.ResourceId >= 0) ResIdMap[sfx.ResourceId] = S_sfx.Size() - 1; + return (int)S_sfx.Size() - 1; +} + + +//========================================================================== +// +// S_FindSoundTentative +// +// Given a logical name, find the sound's index in S_sfx without +// using the hash table. If it does not exist, a new sound without +// an associated lump is created. +//========================================================================== + +int SoundEngine::FindSoundTentative(const char* name) +{ + int id = FindSoundNoHash(name); + if (id == 0) + { + id = AddSoundLump(name, -1, 0); + S_sfx[id].bTentative = true; + } + return id; +} + + +//========================================================================== +// +// S_CacheRandomSound +// +// Loads all sounds a random sound might play. +// +//========================================================================== + +void SoundEngine::CacheRandomSound(sfxinfo_t* sfx) +{ + if (sfx->bRandomHeader) + { + const FRandomSoundList* list = &S_rnd[sfx->link]; + for (unsigned i = 0; i < list->Choices.Size(); ++i) + { + sfx = &S_sfx[list->Choices[i]]; + sfx->bUsed = true; + CacheSound(&S_sfx[list->Choices[i]]); + } + } +} + +//========================================================================== +// +// S_GetSoundMSLength +// +// Returns duration of sound +// GZDoom does not use this due to player sound handling +// +//========================================================================== + +unsigned int SoundEngine::GetMSLength(FSoundID sound) +{ + if ((unsigned int)sound >= S_sfx.Size()) + { + return 0; + } + + sfxinfo_t* sfx = &S_sfx[sound]; + + // Resolve player sounds, random sounds, and aliases + if (sfx->link != sfxinfo_t::NO_LINK) + { + if (sfx->bRandomHeader) + { + // Hm... What should we do here? + // Pick the longest or the shortest sound? + // I think the longest one makes more sense. + + int length = 0; + const FRandomSoundList* list = &S_rnd[sfx->link]; + + for (auto& me : list->Choices) + { + // unfortunately we must load all sounds to find the longest one... :( + int thislen = GetMSLength(me); + if (thislen > length) length = thislen; + } + return length; + } + else + { + sfx = &S_sfx[sfx->link]; + } + } + + sfx = LoadSound(sfx, nullptr); + if (sfx != NULL) return GSnd->GetMSLength(sfx->data); + else return 0; +} + +//========================================================================== +// +// S_PickReplacement +// +// Picks a replacement sound from the associated random list. If this sound +// is not the head of a random list, then the sound passed is returned. +//========================================================================== + +int SoundEngine::PickReplacement(int refid) +{ + while (S_sfx[refid].bRandomHeader) + { + const FRandomSoundList* list = &S_rnd[S_sfx[refid].link]; + refid = list->Choices[rand() % int(list->Choices.Size())]; + } + return refid; +} + +//========================================================================== +// +// S_HashSounds +// +// Fills in the next and index fields of S_sfx to form a working hash table. +//========================================================================== + +void SoundEngine::HashSounds() +{ + unsigned int i; + unsigned int j; + unsigned int size; + + S_sfx.ShrinkToFit(); + size = S_sfx.Size(); + + // Mark all buckets as empty + for (i = 0; i < size; i++) + S_sfx[i].index = 0; + + // Now set up the chains + for (i = 1; i < size; i++) + { + j = MakeKey(S_sfx[i].name) % size; + S_sfx[i].next = S_sfx[j].index; + S_sfx[j].index = i; + } + S_rnd.ShrinkToFit(); +} + +void SoundEngine::AddRandomSound(int Owner, TArray list) +{ + auto index = S_rnd.Reserve(1); + auto& random = S_rnd.Last(); + random.Choices = std::move(list); + random.Owner = Owner; + S_sfx[Owner].link = index; + S_sfx[Owner].bRandomHeader = true; + S_sfx[Owner].NearLimit = -1; +} + +extern ReverbContainer* ForcedEnvironment; + +CVAR(Bool, snd_reverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +void FX_SetReverb(int strength) +{ + if (snd_reverb) + { + // todo: optimize environments. The original "reverb" was garbage and not usable as reference. + if (strength < 64) strength = 0x1400; + else if (strength < 192) strength = 0x1500; + else strength = 0x1900; + ForcedEnvironment = S_FindEnvironment(strength); + } +} + + +#include "basics.h" +#include "stats.h" +#include "v_text.h" +//========================================================================== +// +// S_NoiseDebug +// +// [RH] Print sound debug info. Called by status bar. +//========================================================================== + +FString SoundEngine::NoiseDebug() +{ + FVector3 listener; + FVector3 origin; + + listener = this->listener.position; + int ch = 0; + + FStringf out("*** SOUND DEBUG INFO ***\nListener: %3.2f %2.3f %2.3f\n" + "x y z vol dist chan pri flags aud pos name\n", listener.X, listener.Y, listener.Z); + + if (Channels == nullptr) + { + return out; + } + + for (auto chan = Channels; chan; chan = chan->NextChan) + { + if (!(chan->ChanFlags & CHANF_IS3D)) + { + out += "--- --- --- --- "; + } + else + { + CalcPosVel(chan, &origin, nullptr); + out.AppendFormat(TEXTCOLOR_GOLD "%5.0f | %5.0f | %5.0f | %5.0f ", origin.X, origin.Z, origin.Y, (origin - listener).Length()); + } + out.AppendFormat("%-.2g %-4d %-4d %s3%sZ%sU%sM%sN%sA%sL%sE%sV" TEXTCOLOR_GOLD " %-5.4f %-4u %d: %s\n", chan->Volume, chan->EntChannel, chan->Priority, + (chan->ChanFlags & CHANF_IS3D) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHANF_LISTENERZ) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHANF_UI) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHANF_MAYBE_LOCAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHANF_NOPAUSE) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHANF_AREA) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHANF_LOOP) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHANF_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + (chan->ChanFlags & CHANF_VIRTUAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK, + GSnd->GetAudibility(chan), GSnd->GetPosition(chan), ((int)chan->OrgID)-1, S_sfx[chan->SoundID].name.GetChars()); + ch++; + } + out.AppendFormat("%d channels\n", ch); + return out; +} + +ADD_STAT(sounddebug) +{ + return soundEngine->NoiseDebug(); +} + + diff --git a/source/common/sound/s_soundinternal.h b/source/common/sound/s_soundinternal.h new file mode 100644 index 000000000..2241ffede --- /dev/null +++ b/source/common/sound/s_soundinternal.h @@ -0,0 +1,447 @@ +#pragma once + +#include "backend/i_sound.h" + +struct FRandomSoundList +{ + TArray Choices; + uint32_t Owner = 0; +}; + +extern int sfx_empty; + +// +// SoundFX struct. +// +struct sfxinfo_t +{ + // Next field is for use by the system sound interface. + // A non-null data means the sound has been loaded. + SoundHandle data; + // Also for the sound interface. Used for 3D positional + // sounds, may be the same as data. + SoundHandle data3d; + + FString name; // [RH] Sound name defined in SNDINFO + int lumpnum; // lump number of sfx + + unsigned int next, index; // [RH] For hashing + float Volume; + + int ResourceId; // Resource ID as implemented by Blood. Not used by Doom but added for completeness. + uint8_t PitchMask; + int16_t NearLimit; // 0 means unlimited + float LimitRange; // Range for sound limiting (squared for faster computations) + + unsigned bRandomHeader:1; + unsigned bLoadRAW:1; + unsigned b16bit:1; + unsigned bUsed:1; + unsigned bSingular:1; + + unsigned bTentative:1; + TArray UserData; + + int RawRate; // Sample rate to use when bLoadRAW is true + + int LoopStart; // -1 means no specific loop defined + + unsigned int link; + enum { NO_LINK = 0xffffffff }; + + FRolloffInfo Rolloff; + float Attenuation; // Multiplies the attenuation passed to S_Sound. + + void MarkUsed(); // Marks this sound as used. + + void Clear() + { + data.Clear(); + data3d.Clear(); + lumpnum = -1; // lump number of sfx + next = -1; + index = 0; // [RH] For hashing + Volume = 1.f; + ResourceId = -1; + PitchMask = 0; + NearLimit = 4; // 0 means unlimited + LimitRange = 256*256; + + bRandomHeader = false; + bLoadRAW = false; + b16bit= false; + bUsed = false; + bSingular = false; + + bTentative = true; + + RawRate = 0; // Sample rate to use when bLoadRAW is true + + LoopStart = 0; // -1 means no specific loop defined + + link = NO_LINK; + + Rolloff = {}; + Attenuation = 1.f; + } +}; + +// Rolloff types +enum +{ + ROLLOFF_Doom, // Linear rolloff with a logarithmic volume scale + ROLLOFF_Linear, // Linear rolloff with a linear volume scale + ROLLOFF_Log, // Logarithmic rolloff (standard hardware type) + ROLLOFF_Custom // Lookup volume from SNDCURVE +}; + +int S_FindSound(const char *logicalname); +int S_FindSoundByResID(int snd_id); + +// An index into the S_sfx[] array. +class FSoundID +{ +public: + FSoundID() = default; + + static FSoundID byResId(int ndx) + { + return FSoundID(S_FindSoundByResID(ndx)); + } + FSoundID(int id) + { + ID = id; + } + FSoundID(const char *name) + { + ID = S_FindSound(name); + } + FSoundID(const FString &name) + { + ID = S_FindSound(name.GetChars()); + } + FSoundID(const FSoundID &other) = default; + FSoundID &operator=(const FSoundID &other) = default; + FSoundID &operator=(const char *name) + { + ID = S_FindSound(name); + return *this; + } + FSoundID &operator=(const FString &name) + { + ID = S_FindSound(name.GetChars()); + return *this; + } + bool operator !=(FSoundID other) const + { + return ID != other.ID; + } + bool operator !=(int other) const + { + return ID != other; + } + operator int() const + { + return ID; + } +private: + int ID; +protected: + enum EDummy { NoInit }; + FSoundID(EDummy) {} +}; + + class FSoundIDNoInit : public FSoundID +{ +public: + FSoundIDNoInit() : FSoundID(NoInit) {} + using FSoundID::operator=; +}; + + + +struct FSoundChan : public FISoundChannel +{ + FSoundChan *NextChan; // Next channel in this list. + FSoundChan **PrevChan; // Previous channel in this list. + FSoundID SoundID; // Sound ID of playing sound. + FSoundID OrgID; // Sound ID of sound used to start this channel. + float Volume; + int EntChannel; // Actor's sound channel. + int16_t Pitch; // Pitch variation. + int16_t NearLimit; + int8_t Priority; + uint8_t SourceType; + float LimitRange; + const void *Source; + float Point[3]; // Sound is not attached to any source. +}; + + +// sound channels +// channel 0 never willingly overrides +// other channels (1-7) always override a playing sound on that channel +// +// CHAN_AUTO searches down from channel 7 until it finds a channel not in use +// CHAN_WEAPON is for weapons +// CHAN_VOICE is for oof, sight, or other voice sounds +// CHAN_ITEM is for small things and item pickup +// CHAN_BODY is for generic body sounds +// CHAN_PICKUP can optionally be set as a local sound only for "compatibility" + +enum EChannel +{ + CHAN_AUTO = 0, + CHAN_WEAPON = 1, + CHAN_VOICE = 2, + CHAN_ITEM = 3, + CHAN_BODY = 4, + CHAN_5 = 5, + CHAN_6 = 6, + CHAN_7 = 7, +}; + + + +// sound attenuation values +#define ATTN_NONE 0.f // full volume the entire level +#define ATTN_NORM 1.f +#define ATTN_IDLE 1.001f +#define ATTN_STATIC 3.f // diminish very rapidly with distance + +enum // This cannot be remain as this, but for now it has to suffice. +{ + SOURCE_Any = -1, // Input for check functions meaning 'any source' + SOURCE_None, // Sound is always on top of the listener. + SOURCE_Actor, // Sound is coming from an actor. + SOURCE_Ambient, // Sound is coming from a blood ambient definition. + SOURCE_Unattached, // Sound is not attached to any particular emitter. + SOURCE_Player, // SW player sound (player in SW maintains its own position separately from the sprite so needs to be special.) +}; + + +extern ReverbContainer *Environments; +extern ReverbContainer *DefaultEnvironments[26]; + +void S_ParseReverbDef (); +void S_UnloadReverbDef (); +void S_SetEnvironment (const ReverbContainer *settings); +ReverbContainer *S_FindEnvironment (const char *name); +ReverbContainer *S_FindEnvironment (int id); +void S_AddEnvironment (ReverbContainer *settings); + +class SoundEngine +{ +protected: + bool SoundPaused = false; // whether sound is paused + int RestartEvictionsAt = 0; // do not restart evicted channels before this time + SoundListener listener{}; + + FSoundChan* Channels = nullptr; + FSoundChan* FreeChannels = nullptr; + + // the complete set of sound effects + TArray S_sfx; + FRolloffInfo S_Rolloff; + TArray S_SoundCurve; + TMap ResIdMap; + TArray S_rnd; + +private: + void LoadSound3D(sfxinfo_t* sfx, FSoundLoadBuffer* pBuffer); + void LinkChannel(FSoundChan* chan, FSoundChan** head); + void UnlinkChannel(FSoundChan* chan); + void ReturnChannel(FSoundChan* chan); + void RestartChannel(FSoundChan* chan); + void RestoreEvictedChannel(FSoundChan* chan); + + bool IsChannelUsed(int sourcetype, const void* actor, int channel, int* seen); + // This is the actual sound positioning logic which needs to be provided by the client. + virtual void CalcPosVel(int type, const void* source, const float pt[3], int channel, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan *chan) = 0; + // This can be overridden by the clent to provide some diagnostics. The default lets everything pass. + virtual bool ValidatePosVel(int sourcetype, const void* source, const FVector3& pos, const FVector3& vel) { return true; } + + bool ValidatePosVel(const FSoundChan* const chan, const FVector3& pos, const FVector3& vel); + + // Checks if a copy of this sound is already playing. + bool CheckSingular(int sound_id); + bool CheckSoundLimit(sfxinfo_t* sfx, const FVector3& pos, int near_limit, float limit_range, int sourcetype, const void* actor, int channel); + virtual TArray ReadSound(int lumpnum) = 0; +protected: + virtual FSoundID ResolveSound(const void *ent, int srctype, FSoundID soundid, float &attenuation); + +public: + virtual ~SoundEngine() = default; + void EvictAllChannels(); + + void StopChannel(FSoundChan* chan); + sfxinfo_t* LoadSound(sfxinfo_t* sfx, FSoundLoadBuffer* pBuffer); + + // Initializes sound stuff, including volume + // Sets channels, SFX and music volume, + // allocates channel buffer, sets S_sfx lookup. + // + void Init(TArray &sndcurve); + void InitData(); + void Clear(); + void Shutdown(); + + void StopAllChannels(void); + void SetPitch(FSoundChan* chan, float dpitch); + void SetVolume(FSoundChan* chan, float vol); + + FSoundChan* GetChannel(void* syschan); + void RestoreEvictedChannels(); + void CalcPosVel(FSoundChan* chan, FVector3* pos, FVector3* vel); + + // Loads a sound, including any random sounds it might reference. + void CacheSound(sfxinfo_t* sfx); + void CacheSound(int sfx) { CacheSound(&S_sfx[sfx]); } + void UnloadSound(sfxinfo_t* sfx); + + void UpdateSounds(int time); + + FSoundChan* StartSound(int sourcetype, const void* source, + const FVector3* pt, int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, FRolloffInfo* rolloff = nullptr, float spitch = 0.0f); + + // Stops an origin-less sound from playing from this channel. + void StopSoundID(int sound_id); + void StopSound(int channel, int sound_id = -1); + void StopSound(int sourcetype, const void* actor, int channel, int sound_id = -1); + + void RelinkSound(int sourcetype, const void* from, const void* to, const FVector3* optpos); + void ChangeSoundVolume(int sourcetype, const void* source, int channel, double dvolume); + void ChangeSoundPitch(int sourcetype, const void* source, int channel, double pitch, int sound_id = -1); + bool IsSourcePlayingSomething(int sourcetype, const void* actor, int channel, int sound_id = -1); + + // Stop and resume music, during game PAUSE. + int GetSoundPlayingInfo(int sourcetype, const void* source, int sound_id); + void UnloadAllSounds(); + void Reset(); + void MarkUsed(int num); + void CacheMarkedSounds(); + FString NoiseDebug(); + TArray AllActiveChannels(); + + void MarkAllUnused() + { + for (auto & s: S_sfx) s.bUsed = false; + } + + bool isListener(const void* object) const + { + return object && listener.ListenerObject == object; + } + void SetListener(SoundListener& l) + { + listener = l; + } + void SetRestartTime(int time) + { + RestartEvictionsAt = time; + } + void SetPaused(bool on) + { + SoundPaused = on; + } + FSoundChan* GetChannels() + { + return Channels; + } + const char *GetSoundName(FSoundID id) + { + return id == 0 ? "" : S_sfx[id].name.GetChars(); + } + TArray &GetSounds() //Thio should only be used for constructing the sound list or for diagnostics code prinring information about the sound list. + { + return S_sfx; + } + FRolloffInfo& GlobalRolloff() // like GetSounds this is meant for sound list generators, not for gaining cheap access to the sound engine's innards. + { + return S_Rolloff; + } + FRandomSoundList *ResolveRandomSound(sfxinfo_t* sfx) + { + return &S_rnd[sfx->link]; + } + void ClearRandoms() + { + S_rnd.Clear(); + } + void *GetUserData(int snd) + { + return S_sfx[snd].UserData.Data(); + } + bool isValidSoundId(int id) + { + return id > 0 && id < (int)S_sfx.Size() && !S_sfx[id].bTentative && S_sfx[id].lumpnum != sfx_empty; + } + + template bool EnumerateChannels(func callback) + { + for (FSoundChan* chan = Channels; chan; chan = chan->NextChan) + { + int res = callback(chan); + if (res) return res > 0; + } + return false; + } + + void SetDefaultRolloff(FRolloffInfo* ro) + { + S_Rolloff = *ro; + } + + void ChannelVirtualChanged(FISoundChannel* ichan, bool is_virtual); + FString ListSoundChannels(); + + // Allow this to be overridden for special needs. + virtual float GetRolloff(const FRolloffInfo* rolloff, float distance); + virtual void ChannelEnded(FISoundChannel* ichan); // allows the client to do bookkeeping on the sound. + + // Lookup utilities. + int FindSound(const char* logicalname); + int FindSoundByResID(int rid); + int FindSoundNoHash(const char* logicalname); + int FindSoundByLump(int lump); + int AddSoundLump(const char* logicalname, int lump, int CurrentPitchMask, int resid = -1, int nearlimit = 2); + int AddSfx(sfxinfo_t &sfx); + int FindSoundTentative(const char* name); + void CacheRandomSound(sfxinfo_t* sfx); + unsigned int GetMSLength(FSoundID sound); + int PickReplacement(int refid); + void HashSounds(); + void AddRandomSound(int Owner, TArray list); +}; + + +extern SoundEngine* soundEngine; + +struct FReverbField +{ + int Min, Max; + float REVERB_PROPERTIES::* Float; + int REVERB_PROPERTIES::* Int; + unsigned int Flag; +}; + +inline void FX_StopAllSounds(void) +{ + soundEngine->StopAllChannels(); +} + +void FX_SetReverb(int strength); + +inline void FX_SetReverbDelay(int delay) +{ +} + +inline int S_FindSoundByResID(int ndx) +{ + return soundEngine->FindSoundByResID(ndx); +} + +inline int S_FindSound(const char* name) +{ + return soundEngine->FindSound(name); +} diff --git a/source/common/music/thirdparty/al.h b/source/common/sound/thirdparty/al.h similarity index 100% rename from source/common/music/thirdparty/al.h rename to source/common/sound/thirdparty/al.h diff --git a/source/common/music/thirdparty/alc.h b/source/common/sound/thirdparty/alc.h similarity index 100% rename from source/common/music/thirdparty/alc.h rename to source/common/sound/thirdparty/alc.h diff --git a/source/common/music/thirdparty/alext.h b/source/common/sound/thirdparty/alext.h similarity index 100% rename from source/common/music/thirdparty/alext.h rename to source/common/sound/thirdparty/alext.h diff --git a/source/common/textures/buildtiles.cpp b/source/common/textures/buildtiles.cpp index 4c320f527..fded6c4ad 100644 --- a/source/common/textures/buildtiles.cpp +++ b/source/common/textures/buildtiles.cpp @@ -37,7 +37,7 @@ #include "zstring.h" #include "textures.h" #include "image.h" -#include "cache1d.h" + #include "baselayer.h" #include "palette.h" #include "m_crc32.h" diff --git a/source/common/textures/formats/arttexture.cpp b/source/common/textures/formats/arttexture.cpp index b5c1157fd..624640d48 100644 --- a/source/common/textures/formats/arttexture.cpp +++ b/source/common/textures/formats/arttexture.cpp @@ -37,7 +37,7 @@ #include "templates.h" #include "bitmap.h" #include "image.h" -#include "cache1d.h" + #include "build.h" diff --git a/source/common/utility/namedef.h b/source/common/utility/namedef.h index 3fdb641b3..3f0048f4a 100644 --- a/source/common/utility/namedef.h +++ b/source/common/utility/namedef.h @@ -14,6 +14,10 @@ xx(SEQ) xx(SFX) xx(RAW) xx(MAP) +xx(WAV) +xx(OGG) +xx(FLAC) +xx(VOC) xx(Controlmessage) xx(MainMenu) @@ -43,4 +47,7 @@ xx(EndgameMenu) xx(Mididevices) xx(Aldevices) xx(Alresamplers) -xx(AdvSoundOptions) \ No newline at end of file +xx(AdvSoundOptions) +xx(JoystickConfigMenu) +xx(JoystickOptions) + diff --git a/source/common/utility/tflags.h b/source/common/utility/tflags.h new file mode 100644 index 000000000..98516fce8 --- /dev/null +++ b/source/common/utility/tflags.h @@ -0,0 +1,108 @@ +/* +** tflags.h +** +**--------------------------------------------------------------------------- +** Copyright 2015 Teemu Piippo +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#pragma once + +/* + * TFlags + * + * A Qt-inspired type-safe flagset type. + * + * T is the enum type of individual flags, + * TT is the underlying integer type used (defaults to uint32_t) + */ +template +class TFlags +{ + struct ZeroDummy {}; + +public: + typedef TFlags Self; + typedef T EnumType; + typedef TT IntType; + + TFlags() = default; + TFlags(const Self& other) = default; + TFlags (T value) : Value (static_cast (value)) {} + + // This allows initializing the flagset with 0, as 0 implicitly converts into a null pointer. + TFlags (ZeroDummy*) : Value (0) {} + + // Relation operators + Self operator| (Self other) const { return Self::FromInt (Value | other.GetValue()); } + Self operator& (Self other) const { return Self::FromInt (Value & other.GetValue()); } + Self operator^ (Self other) const { return Self::FromInt (Value ^ other.GetValue()); } + Self operator| (T value) const { return Self::FromInt (Value | value); } + Self operator& (T value) const { return Self::FromInt (Value & value); } + Self operator^ (T value) const { return Self::FromInt (Value ^ value); } + Self operator~() const { return Self::FromInt (~Value); } + + // Assignment operators + Self& operator= (Self other) { Value = other.GetValue(); return *this; } + Self& operator|= (Self other) { Value |= other.GetValue(); return *this; } + Self& operator&= (Self other) { Value &= other.GetValue(); return *this; } + Self& operator^= (Self other) { Value ^= other.GetValue(); return *this; } + Self& operator= (T value) { Value = value; return *this; } + Self& operator|= (T value) { Value |= value; return *this; } + Self& operator&= (T value) { Value &= value; return *this; } + Self& operator^= (T value) { Value ^= value; return *this; } + + // Access the value of the flagset + TT GetValue() const { return Value; } + operator TT() const { return Value; } + + // Set the value of the flagset manually with an integer. + // Please think twice before using this. + static Self FromInt (TT value) { return Self (static_cast (value)); } + +private: + template Self operator| (X value) const { return Self::FromInt (Value | value); } + template Self operator& (X value) const { return Self::FromInt (Value & value); } + template Self operator^ (X value) const { return Self::FromInt (Value ^ value); } + +public: // to be removed. + TT Value; +}; + +/* + * Additional operators for TFlags types. + */ +#define DEFINE_TFLAGS_OPERATORS(T) \ +inline T operator| (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ +inline T operator& (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ +inline T operator^ (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ +inline T operator| (T::EnumType a, T b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \ +inline T operator& (T::EnumType a, T b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \ +inline T operator^ (T::EnumType a, T b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \ +inline T operator~ (T::EnumType a) { return T::FromInt (~T::IntType (a)); } + diff --git a/source/duke3d/CMakeLists.txt b/source/duke3d/CMakeLists.txt index b3169684e..4af68f588 100644 --- a/source/duke3d/CMakeLists.txt +++ b/source/duke3d/CMakeLists.txt @@ -7,14 +7,13 @@ endif() include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/../../build/include" ) if (WIN32) - include_directories( "${ZLIB_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/vpx" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/sdl2" ) + include_directories( "${ZLIB_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/vpx" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/sdl2" ) else () -include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GDTOA_INCLUDE_DIR}") +include_directories( "${ZLIB_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GDTOA_INCLUDE_DIR}") endif() include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../build/include - ${CMAKE_CURRENT_SOURCE_DIR}/../mact/include ${CMAKE_CURRENT_SOURCE_DIR}/../audiolib/include ${CMAKE_CURRENT_SOURCE_DIR}/../libsmackerdec/include ${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/include @@ -25,6 +24,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../common/fonts ${CMAKE_CURRENT_SOURCE_DIR}/../common/2d ${CMAKE_CURRENT_SOURCE_DIR}/../common/music + ${CMAKE_CURRENT_SOURCE_DIR}/../common/input ${CMAKE_CURRENT_SOURCE_DIR}/../platform ) diff --git a/source/duke3d/src/actors.cpp b/source/duke3d/src/actors.cpp index d7e43c61f..b298cdff5 100644 --- a/source/duke3d/src/actors.cpp +++ b/source/duke3d/src/actors.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define actors_c_ #include "duke3d.h" +#include "sounds.h" BEGIN_DUKE_NS @@ -1485,14 +1486,14 @@ ACTOR_STATIC void G_MoveFX(void) else if (playerDist >= spriteHitag && T1(spriteNum) == 1) { FX_SetReverb(0); - FX_SetReverbDelay(0); T1(spriteNum) = 0; } } else if (pSprite->lotag < 999 && (unsigned)sector[pSprite->sectnum].lotag < 9 && // ST_9_SLIDING_ST_DOOR snd_ambience && sector[SECT(spriteNum)].floorz != sector[SECT(spriteNum)].ceilingz) { - if (g_sounds[pSprite->lotag].m & SF_MSFX) + auto flags = S_GetUserFlags(pSprite->lotag); + if (flags & SF_MSFX) { int playerDist = dist(&sprite[pPlayer->i], pSprite); @@ -1505,10 +1506,10 @@ ACTOR_STATIC void G_MoveFX(void) } #endif - if (playerDist < spriteHitag && T1(spriteNum) == 0 && FX_VoiceAvailable(g_sounds[pSprite->lotag].pr-1)) + if (playerDist < spriteHitag && T1(spriteNum) == 0)// && FX_VoiceAvailable(g_sounds[pSprite->lotag].pr-1)) { // Start playing an ambience sound. - +#if 0 // let the sound system handle this internally. char om = g_sounds[pSprite->lotag].m; if (g_numEnvSoundsPlaying == snd_numvoices) { @@ -1525,10 +1526,8 @@ ACTOR_STATIC void G_MoveFX(void) if (j == -1) goto next_sprite; } - - g_sounds[pSprite->lotag].m |= SF_LOOP; - A_PlaySound(pSprite->lotag,spriteNum); - g_sounds[pSprite->lotag].m = om; +#endif + A_PlaySound(pSprite->lotag,spriteNum, CHAN_AUTO, CHANF_LOOP); T1(spriteNum) = 1; // AMBIENT_SFX_PLAYING } else if (playerDist >= spriteHitag && T1(spriteNum) == 1) @@ -1541,7 +1540,7 @@ ACTOR_STATIC void G_MoveFX(void) } } - if ((g_sounds[pSprite->lotag].m & (SF_GLOBAL|SF_DTAG)) == SF_GLOBAL) + if ((flags & (SF_GLOBAL|SF_DTAG)) == SF_GLOBAL) { // Randomly playing global sounds (flyby of planes, screams, ...) diff --git a/source/duke3d/src/anim.cpp b/source/duke3d/src/anim.cpp index 3af7e8d8d..76e74dd8e 100644 --- a/source/duke3d/src/anim.cpp +++ b/source/duke3d/src/anim.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "renderlayer.h" #include "duke3d.h" #include "animlib.h" -#include "mouse.h" #include "compat.h" #include "input.h" @@ -365,7 +364,7 @@ int32_t Anim_Play(const char *fn) if (sound == -1) FX_StopAllSounds(); else - S_PlaySound(sound); + S_PlaySound(sound, CHAN_AUTO, CHANF_UI); soundidx++; } @@ -379,7 +378,7 @@ int32_t Anim_Play(const char *fn) if (sound == -1) FX_StopAllSounds(); else - S_PlaySound(sound); + S_PlaySound(sound, CHAN_AUTO, CHANF_UI); soundidx++; } @@ -537,7 +536,7 @@ int32_t Anim_Play(const char *fn) if (sound == -1) FX_StopAllSounds(); else - S_PlaySound(sound); + S_PlaySound(sound, CHAN_AUTO, CHANF_UI); soundidx++; } diff --git a/source/duke3d/src/config.cpp b/source/duke3d/src/config.cpp index 93d36764a..6922be453 100644 --- a/source/duke3d/src/config.cpp +++ b/source/duke3d/src/config.cpp @@ -77,14 +77,7 @@ void CONFIG_SetDefaults(void) ud.display_bonus_screen = 1; hud_position = 0; - ud.menu_scrollbartilenum = -1; - ud.menu_scrollbarz = 65536; - ud.menu_scrollcursorz = 65536; - ud.menu_slidebarmargin = 65536; - ud.menu_slidebarz = 65536; - ud.menu_slidecursorz = 65536; ud.menubackground = 1; - ud.runkey_mode = 0; ud.screen_size = 4; ud.screen_tilting = 1; ud.screenfade = 1; diff --git a/source/duke3d/src/d_menu.cpp b/source/duke3d/src/d_menu.cpp index 38e3822bf..d113a82e6 100644 --- a/source/duke3d/src/d_menu.cpp +++ b/source/duke3d/src/d_menu.cpp @@ -481,15 +481,15 @@ void GameInterface::MenuSound(EMenuSounds snd) switch (snd) { case CursorSound: - S_PlaySound(KICK_HIT); + S_PlaySound(KICK_HIT, CHAN_AUTO, CHANF_UI); break; case AdvanceSound: - S_PlaySound(PISTOL_BODYHIT); + S_PlaySound(PISTOL_BODYHIT, CHAN_AUTO, CHANF_UI); break; case CloseSound: - S_PlaySound(EXITMENUSOUND); + S_PlaySound(EXITMENUSOUND, CHAN_AUTO, CHANF_UI); break; default: @@ -568,7 +568,16 @@ void GameInterface::StartGame(FGameStartup& gs) } ud.m_player_skill = gs.Skill + 1; - if (menu_sounds) ud.skill_voice = S_PlaySound(skillsound); + if (menu_sounds && skillsound >= 0 && SoundEnabled()) + { + S_PlaySound(skillsound, CHAN_AUTO, CHANF_UI); + + while (S_CheckSoundPlaying(skillsound)) + { + S_Update(); + gameHandleEvents(); + } + } ud.m_respawn_monsters = (gs.Skill == 3); ud.m_monsters_off = ud.monsters_off = 0; ud.m_respawn_items = 0; diff --git a/source/duke3d/src/duke3d.h b/source/duke3d/src/duke3d.h index 21e187a22..d8c4dc5de 100644 --- a/source/duke3d/src/duke3d.h +++ b/source/duke3d/src/duke3d.h @@ -27,10 +27,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "a.h" #include "baselayer.h" #include "build.h" -#include "cache1d.h" + #include "compat.h" -#include "fx_man.h" -#include "keyboard.h" #include "pragmas.h" #include "polymost.h" #include "gamecvars.h" @@ -112,7 +110,6 @@ EDUKE32_STATIC_ASSERT(7 <= MAXTILES-MAXUSERTILES); #include "actors.h" #include "common_game.h" #include "config.h" -#include "control.h" #include "gamecontrol.h" #include "game.h" #include "gamedef.h" @@ -121,7 +118,6 @@ EDUKE32_STATIC_ASSERT(7 <= MAXTILES-MAXUSERTILES); #include "global.h" #include "inv.h" #include "macros.h" -#include "music.h" #include "namesdyn.h" #include "network.h" #include "player.h" diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index 644425f06..219487beb 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -172,9 +172,7 @@ enum gametokens static void gameTimerHandler(void) { - S_Cleanup(); - MUSIC_Update(); - + S_Update(); G_HandleSpecialKeys(); } @@ -4394,16 +4392,15 @@ void G_InitTimer(int32_t ticspersec) static int32_t g_RTSPlaying; // Returns: started playing? -extern int G_StartRTS(int lumpNum, int localPlayer) +int G_StartRTS(int lumpNum, int localPlayer) { if (!adult_lockout && SoundEnabled() && RTS_IsInitialized() && g_RTSPlaying == 0 && (snd_speech & (localPlayer ? 1 : 4))) { - char *const pData = (char *)RTS_GetSound(lumpNum - 1); - - if (pData != NULL) + auto sid = RTS_GetSoundID(lumpNum - 1); + if (sid != -1) { - FX_Play3D(pData, RTS_SoundLength(lumpNum - 1), FX_ONESHOT, 0, 0, 1, 255, 1.f, -lumpNum); + S_PlaySound(sid, CHAN_AUTO, CHANF_UI); g_RTSPlaying = 7; return 1; } @@ -4493,7 +4490,7 @@ void G_HandleLocalKeys(void) { if (G_ChangeHudLayout(1)) { - S_PlaySound(THUD); + S_PlaySound(THUD, CHAN_AUTO, CHANF_UI); } } else @@ -4512,7 +4509,7 @@ void G_HandleLocalKeys(void) { if (G_ChangeHudLayout(-1)) { - S_PlaySound(THUD); + S_PlaySound(THUD, CHAN_AUTO, CHANF_UI); } } else @@ -4746,43 +4743,6 @@ void G_HandleLocalKeys(void) } } -static int32_t S_DefineAudioIfSupported(char **fn, const char *name) -{ -#if !defined HAVE_FLAC || !defined HAVE_VORBIS - const char *extension = Bstrrchr(name, '.'); -# if !defined HAVE_FLAC - if (extension && !Bstrcasecmp(extension, ".flac")) - return -2; -# endif -# if !defined HAVE_VORBIS - if (extension && !Bstrcasecmp(extension, ".ogg")) - return -2; -# endif -#endif - realloc_copy(fn, name); - return 0; -} - -static int32_t S_DefineSound(int sndidx, const char *name, int minpitch, int maxpitch, int priority, int type, int distance, float volume) -{ - if ((unsigned)sndidx >= MAXSOUNDS || S_DefineAudioIfSupported(&g_sounds[sndidx].filename, name)) - return -1; - - auto &snd = g_sounds[sndidx]; - - snd.ps = clamp(minpitch, INT16_MIN, INT16_MAX); - snd.pe = clamp(maxpitch, INT16_MIN, INT16_MAX); - snd.pr = priority & 255; - snd.m = type & ~SF_ONEINST_INTERNAL; - snd.vo = clamp(distance, INT16_MIN, INT16_MAX); - snd.volume = volume; - - if (snd.m & SF_LOOP) - snd.m |= SF_ONEINST_INTERNAL; - - return 0; -} - // Returns: // 0: all OK // -1: ID declaration was invalid: @@ -5365,7 +5325,7 @@ int loaddefinitions_game(const char *fileName, int32_t firstPass) if (pScript) parsedefinitions_game(pScript, firstPass); - for (auto& m : *userConfig.AddDefs) + if (userConfig.AddDefs) for (auto& m : *userConfig.AddDefs) parsedefinitions_game_include(m, NULL, "null", firstPass); if (pScript) @@ -5400,10 +5360,6 @@ static void G_Cleanup(void) Xfree(g_player[i].input); } - for (i=MAXSOUNDS-1; i>=0; i--) - { - Xfree(g_sounds[i].filename); - } #if !defined LUNATIC if (label != (char *)&sprite[0]) Xfree(label); if (labelcode != (int32_t *)§or[0]) Xfree(labelcode); @@ -5433,8 +5389,6 @@ static void G_Cleanup(void) void G_Shutdown(void) { - S_SoundShutdown(); - CONTROL_Shutdown(); engineUnInit(); G_Cleanup(); } @@ -5851,6 +5805,8 @@ int GameInterface::app_main() { I_Error("app_main: There was a problem initializing the Build engine: %s\n", engineerrstr); } + hud_size.Callback(); + S_InitSound(); g_logFlushWindow = 0; @@ -6033,7 +5989,6 @@ int GameInterface::app_main() } videoSetPalette(0, myplayer.palette, 0); - S_SoundStartup(); } // check if the minifont will support lowercase letters (3136-3161) @@ -6203,7 +6158,6 @@ MAIN_LOOP_RESTART: && (myplayer.gm & MODE_GAME)) { G_MoveLoop(); - S_Update(); } if (totalclock - moveClock >= (TICSPERFRAME>>1)) diff --git a/source/duke3d/src/game.h b/source/duke3d/src/game.h index 4b77984cf..c17d64a31 100644 --- a/source/duke3d/src/game.h +++ b/source/duke3d/src/game.h @@ -141,13 +141,11 @@ typedef struct { int32_t camera_time,folfvel,folavel,folx,foly,fola; int32_t reccnt; - int32_t runkey_mode,statusbarscale,weaponswitch; // JBF 20031125 + int32_t statusbarscale,weaponswitch; // JBF 20031125 int32_t statusbarmode; int32_t noexits; int32_t althud; int32_t statusbarflags, statusbarrange; - int32_t menu_slidebarz, menu_slidebarmargin, menu_slidecursorz; - int32_t menu_scrollbartilenum, menu_scrollbarz, menu_scrollcursorz; int32_t entered_name,screen_tilting; int32_t coop,screen_size; @@ -157,7 +155,7 @@ typedef struct { int32_t m_respawn_items,m_respawn_monsters,m_respawn_inventory,m_monsters_off; int32_t ffire,m_player_skill,m_level_number,m_volume_number,multimode; int32_t player_skill,level_number,volume_number,marker; - int32_t music_episode, music_level, skill_voice; + int32_t music_episode, music_level; int32_t playerbest; diff --git a/source/duke3d/src/gamedef.cpp b/source/duke3d/src/gamedef.cpp index 1f2718dff..b8cd4a522 100644 --- a/source/duke3d/src/gamedef.cpp +++ b/source/duke3d/src/gamedef.cpp @@ -2255,6 +2255,7 @@ static void scriptUpdateOpcodeForVariableType(intptr_t *ins) static bool C_ParseCommand(bool loop /*= false*/) { int32_t i, j=0, k=0, tw; + TArray buffer; do { @@ -4960,10 +4961,10 @@ repeatcase: i = 0; { - TArray build; + buffer.Clear(); while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) { - build.Push(*textptr); + buffer.Push(*textptr); textptr++, i++; if (EDUKE32_PREDICT_FALSE(*textptr != 0x0a && *textptr != 0x0d && ispecial(*textptr))) { @@ -4974,8 +4975,8 @@ repeatcase: break; } } - build.Push(0); - C_CON_SetButtonAlias(j, build.Data()); + buffer.Push(0); + C_CON_SetButtonAlias(j, buffer.Data()); } continue; @@ -5246,7 +5247,7 @@ repeatcase: scriptSkipSpaces(); - TArray buffer; + buffer.Clear(); while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) { buffer.Push(*textptr); @@ -5361,86 +5362,70 @@ repeatcase: continue; case CON_DEFINESOUND: + { + int ps, pe, vo, pr, m; + g_scriptPtr--; C_GetNextValue(LABEL_DEFINE); // Ideally we could keep the value of i from C_GetNextValue() instead of having to hash_find() again. // This depends on tempbuf remaining in place after C_GetNextValue(): - j = hash_find(&h_labels,tempbuf); + j = hash_find(&h_labels, tempbuf); k = g_scriptPtr[-1]; - if (EDUKE32_PREDICT_FALSE((unsigned)k >= MAXSOUNDS-1)) + if ((unsigned)k >= MAXSOUNDS - 1) { - initprintf("%s:%d: error: sound index exceeds limit of %d.\n",g_scriptFileName,g_lineNumber, MAXSOUNDS-1); + initprintf("%s:%d: error: sound index exceeds limit of %d.\n", g_scriptFileName, g_lineNumber, MAXSOUNDS - 1); g_errorCnt++; - k = MAXSOUNDS-1; + k = MAXSOUNDS - 1; } - else if (EDUKE32_PREDICT_FALSE(g_sounds[k].filename != NULL)) + /*else if (g_sounds[k].filename != NULL) { - initprintf("%s:%d: warning: sound %d already defined (%s)\n",g_scriptFileName,g_lineNumber,k,g_sounds[k].filename); + initprintf("%s:%d: warning: sound %d already defined (%s)\n", g_scriptFileName, g_lineNumber, k, g_sounds[k].filename); g_warningCnt++; - } + }*/ g_scriptPtr--; i = 0; C_SkipComments(); - if (g_sounds[k].filename == NULL) - g_sounds[k].filename = (char *)Xcalloc(BMAX_PATH,sizeof(uint8_t)); + buffer.Clear(); if (*textptr == '\"') { textptr++; while (*textptr && *textptr != '\"') { - g_sounds[k].filename[i++] = *textptr++; - if (EDUKE32_PREDICT_FALSE(i >= BMAX_PATH-1)) - { - initprintf("%s:%d: error: sound filename exceeds limit of %d characters.\n",g_scriptFileName,g_lineNumber,BMAX_PATH-1); - g_errorCnt++; - C_SkipComments(); - break; - } + buffer.Push(*textptr++); } textptr++; } else while (*textptr != ' ' && *textptr != '\t' && *textptr != '\r' && *textptr != '\n') { - g_sounds[k].filename[i++] = *textptr++; - if (EDUKE32_PREDICT_FALSE(i >= BMAX_PATH-1)) - { - initprintf("%s:%d: error: sound filename exceeds limit of %d characters.\n",g_scriptFileName,g_lineNumber,BMAX_PATH-1); - g_errorCnt++; - C_SkipComments(); - break; - } + buffer.Push(*textptr++); } - g_sounds[k].filename[i] = '\0'; + buffer.Push(0); C_GetNextValue(LABEL_DEFINE); - g_sounds[k].ps = g_scriptPtr[-1]; + ps = g_scriptPtr[-1]; C_GetNextValue(LABEL_DEFINE); - g_sounds[k].pe = g_scriptPtr[-1]; + pe = g_scriptPtr[-1]; C_GetNextValue(LABEL_DEFINE); - g_sounds[k].pr = g_scriptPtr[-1]; + pr = g_scriptPtr[-1]; C_GetNextValue(LABEL_DEFINE); - g_sounds[k].m = g_scriptPtr[-1] & ~SF_ONEINST_INTERNAL; - if (g_scriptPtr[-1] & SF_LOOP) - g_sounds[k].m |= SF_ONEINST_INTERNAL; + m = g_scriptPtr[-1]; C_GetNextValue(LABEL_DEFINE); - g_sounds[k].vo = g_scriptPtr[-1]; + vo = g_scriptPtr[-1]; g_scriptPtr -= 5; - g_sounds[k].volume = 1.f; - - if (k > g_highestSoundIdx) - g_highestSoundIdx = k; + int res = S_DefineSound(k, buffer.Data(), ps, pe, pr, m, vo, 1.f); if (g_dynamicSoundMapping && j >= 0 && (labeltype[j] & LABEL_DEFINE)) - G_ProcessDynamicSoundMapping(label+(j<<6), k); + G_ProcessDynamicSoundMapping(label + (j << 6), k); continue; + } case CON_ENDEVENT: @@ -5952,7 +5937,7 @@ void C_Compile(const char *fileName) C_AddDefaultDefinitions(); C_ParseCommand(true); - for (FString& m : *userConfig.AddCons.get()) + if (userConfig.AddCons) for (FString& m : *userConfig.AddCons.get()) { C_Include(m); } diff --git a/source/duke3d/src/gameexec.cpp b/source/duke3d/src/gameexec.cpp index 4c0df3108..ac814d405 100644 --- a/source/duke3d/src/gameexec.cpp +++ b/source/duke3d/src/gameexec.cpp @@ -4125,7 +4125,7 @@ badindex: if (S_CheckSoundPlaying(soundNum)) S_StopSound((int16_t)soundNum); dispatch(); - case CON_SCREENSOUND: S_PlaySound(soundNum); dispatch(); + case CON_SCREENSOUND: S_PlaySound(soundNum, CHAN_AUTO, CHANF_UI); dispatch(); } } dispatch(); diff --git a/source/duke3d/src/gamestructures.cpp b/source/duke3d/src/gamestructures.cpp index 9ea044ae4..cb56ffa7c 100644 --- a/source/duke3d/src/gamestructures.cpp +++ b/source/duke3d/src/gamestructures.cpp @@ -1473,7 +1473,7 @@ int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2) case USERDEFS_SHOW_LEVEL_TEXT: labelNum = ud.show_level_text; break; case USERDEFS_WEAPONSCALE: labelNum = hud_weaponscale; break; case USERDEFS_TEXTSCALE: labelNum = hud_textscale; break; - case USERDEFS_RUNKEY_MODE: labelNum = ud.runkey_mode; break; + case USERDEFS_RUNKEY_MODE: labelNum = cl_runmode; break; case USERDEFS_M_ORIGIN_X: labelNum = ud.returnvar[0]; break; case USERDEFS_M_ORIGIN_Y: labelNum = ud.returnvar[1]; break; case USERDEFS_PLAYERBEST: labelNum = ud.playerbest; break; @@ -1502,9 +1502,9 @@ int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2) case USERDEFS_STATUSBARRANGE: labelNum = ud.statusbarrange; break; case USERDEFS_STATUSBARCUSTOM: labelNum = hud_custom; break; case USERDEFS_HUDONTOP: labelNum = hud_position; break; - case USERDEFS_MENU_SLIDEBARZ: labelNum = ud.menu_slidebarz; break; - case USERDEFS_MENU_SLIDEBARMARGIN: labelNum = ud.menu_slidebarmargin; break; - case USERDEFS_MENU_SLIDECURSORZ: labelNum = ud.menu_slidecursorz; break; + case USERDEFS_MENU_SLIDEBARZ: labelNum = 65536; break; + case USERDEFS_MENU_SLIDEBARMARGIN: labelNum = 65536; break; + case USERDEFS_MENU_SLIDECURSORZ: labelNum = 65536; break; case USERDEFS_GLOBAL_R: labelNum = globalr; break; case USERDEFS_GLOBAL_G: labelNum = globalg; break; case USERDEFS_GLOBAL_B: labelNum = globalb; break; @@ -1534,9 +1534,9 @@ int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2) case USERDEFS_MUSIC_EPISODE: labelNum = ud.music_episode; break; // Problem: This info is utterly meaningless with the new music system. case USERDEFS_MUSIC_LEVEL: labelNum = ud.music_level; break; case USERDEFS_SHADOW_PAL: labelNum = ud.shadow_pal; break; - case USERDEFS_MENU_SCROLLBARTILENUM: labelNum = ud.menu_scrollbartilenum; break; - case USERDEFS_MENU_SCROLLBARZ: labelNum = ud.menu_scrollbarz; break; - case USERDEFS_MENU_SCROLLCURSORZ: labelNum = ud.menu_scrollcursorz; break; + case USERDEFS_MENU_SCROLLBARTILENUM: labelNum = -1; break; + case USERDEFS_MENU_SCROLLBARZ: labelNum = 65536; break; + case USERDEFS_MENU_SCROLLCURSORZ: labelNum = 65536; break; case USERDEFS_RETURN: if (lParm2 == 0) labelNum = aGameVars[g_returnVarID].global; @@ -1548,7 +1548,7 @@ int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2) case USERDEFS_DRAW_Y: labelNum = rotatesprite_y_offset; break; case USERDEFS_DRAW_YXASPECT: labelNum = rotatesprite_yxaspect; break; case USERDEFS_FOV: labelNum = r_fov; break; - case USERDEFS_GAMEPADACTIVE: labelNum = (CONTROL_LastSeenInput == LastSeenInput::Joystick); break; + case USERDEFS_GAMEPADACTIVE: labelNum = inputState.gamePadActive(); break; default: EDUKE32_UNREACHABLE_SECTION(labelNum = -1; break); } @@ -1666,7 +1666,7 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_SHOW_LEVEL_TEXT: ud.show_level_text = iSet; break; case USERDEFS_WEAPONSCALE: hud_weaponscale.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_TEXTSCALE: hud_textscale.SetGenericRepDefault(iSet, CVAR_Int); break; - case USERDEFS_RUNKEY_MODE: ud.runkey_mode = iSet; break; + case USERDEFS_RUNKEY_MODE: cl_runmode.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_M_ORIGIN_X: ud.returnvar[0] = iSet; break; case USERDEFS_M_ORIGIN_Y: ud.returnvar[1] = iSet; break; case USERDEFS_GLOBALFLAGS: globalflags = iSet; break; @@ -1695,9 +1695,9 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_STATUSBARRANGE: ud.statusbarrange = iSet; break; case USERDEFS_STATUSBARCUSTOM: hud_custom.SetGenericRepDefault(iSet, CVAR_Int); break; case USERDEFS_HUDONTOP: hud_position.SetGenericRepDefault(iSet, CVAR_Int); break; - case USERDEFS_MENU_SLIDEBARZ: ud.menu_slidebarz = iSet; break; - case USERDEFS_MENU_SLIDEBARMARGIN: ud.menu_slidebarmargin = iSet; break; - case USERDEFS_MENU_SLIDECURSORZ: ud.menu_slidecursorz = iSet; break; + case USERDEFS_MENU_SLIDEBARZ: break; + case USERDEFS_MENU_SLIDEBARMARGIN: break; + case USERDEFS_MENU_SLIDECURSORZ: break; case USERDEFS_GLOBAL_R: globalr = iSet; break; case USERDEFS_GLOBAL_G: globalg = iSet; break; case USERDEFS_GLOBAL_B: globalb = iSet; break; @@ -1737,9 +1737,9 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_SLIDEBAR_PALSELECTED: ud.slidebar_palselected = iSet; break; case USERDEFS_SLIDEBAR_PALDISABLED: ud.slidebar_paldisabled = iSet; break; case USERDEFS_SHADOW_PAL: ud.shadow_pal = iSet; break; - case USERDEFS_MENU_SCROLLBARTILENUM: ud.menu_scrollbartilenum = iSet; break; - case USERDEFS_MENU_SCROLLBARZ: ud.menu_scrollbarz = iSet; break; - case USERDEFS_MENU_SCROLLCURSORZ: ud.menu_scrollcursorz = iSet; break; + case USERDEFS_MENU_SCROLLBARTILENUM: break; + case USERDEFS_MENU_SCROLLBARZ: break; + case USERDEFS_MENU_SCROLLCURSORZ: break; case USERDEFS_RETURN: if (lParm2 == 0) aGameVars[g_returnVarID].global = iSet; diff --git a/source/duke3d/src/global.h b/source/duke3d/src/global.h index bfb84f74c..49e1a1e14 100644 --- a/source/duke3d/src/global.h +++ b/source/duke3d/src/global.h @@ -149,7 +149,6 @@ G_EXTERN int32_t g_noEnemies; G_EXTERN int32_t g_restorePalette; G_EXTERN int32_t g_screenCapture; G_EXTERN projectile_t SpriteProjectile[MAXSPRITES]; -G_EXTERN sound_t g_sounds[MAXSOUNDS]; G_EXTERN uint32_t everyothertime; G_EXTERN uint32_t g_moveThingsCount; G_EXTERN double g_gameUpdateTime; diff --git a/source/duke3d/src/osdcmds.cpp b/source/duke3d/src/osdcmds.cpp index 92004f793..5279c2748 100644 --- a/source/duke3d/src/osdcmds.cpp +++ b/source/duke3d/src/osdcmds.cpp @@ -172,19 +172,6 @@ static int osdcmd_noclip(osdcmdptr_t UNUSED(parm)) return OSDCMD_OK; } -static int osdcmd_restartsound(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - S_SoundShutdown(); - - S_SoundStartup(); - - FX_StopAllSounds(); - S_ClearSoundLocks(); - - return OSDCMD_OK; -} - int osdcmd_restartmap(osdcmdptr_t UNUSED(parm)) { UNREFERENCED_CONST_PARAMETER(parm); @@ -812,7 +799,6 @@ int32_t registerosdcommands(void) OSD_RegisterFunction("printtimes", "printtimes: prints VM timing statistics", osdcmd_printtimes); OSD_RegisterFunction("restartmap", "restartmap: restarts the current map", osdcmd_restartmap); - OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound); OSD_RegisterFunction("addlogvar","addlogvar : prints the value of a gamevar", osdcmd_addlogvar); OSD_RegisterFunction("setvar","setvar : sets the value of a gamevar", osdcmd_setvar); OSD_RegisterFunction("setvarvar","setvarvar : sets the value of to ", osdcmd_setvar); diff --git a/source/duke3d/src/player.cpp b/source/duke3d/src/player.cpp index c15ea143f..147c4f3a6 100644 --- a/source/duke3d/src/player.cpp +++ b/source/duke3d/src/player.cpp @@ -3730,13 +3730,7 @@ void P_FragPlayer(int playerNum) pPlayer->holoduke_on = -1; S_StopEnvSound(DUKE_JETPACK_IDLE, pPlayer->i); - - if (pPlayer->scream_voice > FX_Ok) - { - FX_StopSound(pPlayer->scream_voice); - S_Cleanup(); - pPlayer->scream_voice = -1; - } + S_StopEnvSound(-1, pPlayer->i, CHAN_VOICE); } #endif @@ -4997,11 +4991,9 @@ void P_ProcessInput(int playerNum) if (pPlayer->vel.z > 2400 && pPlayer->falling_counter < 255) { pPlayer->falling_counter++; - if (pPlayer->falling_counter >= 38 && pPlayer->scream_voice <= FX_Ok) + if (pPlayer->falling_counter >= 38 && !A_CheckSoundPlaying(pPlayer->i, -1, CHAN_VOICE)) { - int32_t voice = A_PlaySound(DUKE_SCREAM,pPlayer->i); - if (voice <= 127) // XXX: p->scream_voice is an int8_t - pPlayer->scream_voice = voice; + A_PlaySound(DUKE_SCREAM, pPlayer->i, CHAN_VOICE); } } @@ -5045,12 +5037,7 @@ void P_ProcessInput(int playerNum) { pPlayer->falling_counter = 0; - if (pPlayer->scream_voice > FX_Ok) - { - FX_StopSound(pPlayer->scream_voice); - S_Cleanup(); - pPlayer->scream_voice = -1; - } + S_StopEnvSound(-1, pPlayer->i, CHAN_VOICE); if ((sectorLotag != ST_1_ABOVE_WATER && sectorLotag != ST_2_UNDERWATER) && (pPlayer->on_ground == 0 && pPlayer->vel.z > (6144 >> 1))) diff --git a/source/duke3d/src/premap.cpp b/source/duke3d/src/premap.cpp index a48db358e..9955543d4 100644 --- a/source/duke3d/src/premap.cpp +++ b/source/duke3d/src/premap.cpp @@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "menu/menu.h" #include "mapinfo.h" #include "cmdlib.h" + BEGIN_DUKE_NS static uint8_t precachehightile[2][(MAXTILES+7)>>3]; @@ -467,8 +468,6 @@ void G_CacheMapData(void) if (r_precache) PrecacheHardwareTextures(i); #endif - MUSIC_Update(); - if ((++cnt & 7) == 0) gameHandleEvents(); } @@ -1319,12 +1318,6 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum) gameHandleEvents(); - if (ud.skill_voice > 0 && SoundEnabled()) - { - while (FX_SoundActive(ud.skill_voice)) - gameHandleEvents(); - } - ready2send = 0; if (m_recstat != 2 && ud.last_level != -1 && !VM_OnEventWithReturn(EVENT_EXITGAMESCREEN, g_player[myconnectindex].ps->i, myconnectindex, 0) @@ -1338,7 +1331,6 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum) ud.level_number = levelNum; ud.player_skill = skillNum; ud.secretlevel = 0; - ud.skill_voice = -1; ud.volume_number = volumeNum; // we don't want the intro to play after the multiplayer setup screen diff --git a/source/duke3d/src/savegame.cpp b/source/duke3d/src/savegame.cpp index 9c62f961a..626846a65 100644 --- a/source/duke3d/src/savegame.cpp +++ b/source/duke3d/src/savegame.cpp @@ -37,8 +37,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_DUKE_NS -static OutputFileCounter savecounter; - // For storing pointers in files. // back_p==0: ptr -> "small int" // back_p==1: "small int" -> ptr @@ -313,7 +311,6 @@ int32_t G_LoadPlayer(FSaveGameNode *sv) ud.level_number = level; ud.player_skill = skill; ud.secretlevel = 0; - ud.skill_voice = -1; ud.volume_number = volume; #ifdef EDUKE32_TOUCH_DEVICES diff --git a/source/duke3d/src/screens.cpp b/source/duke3d/src/screens.cpp index 8be60fbb5..f1fc6e59e 100644 --- a/source/duke3d/src/screens.cpp +++ b/source/duke3d/src/screens.cpp @@ -2055,7 +2055,6 @@ void G_BonusScreen(int32_t bonusonly) while (totalclock < TICRATE*10) { gameHandleEvents(); - MUSIC_Update(); if (G_FPSLimit()) { @@ -2099,7 +2098,6 @@ void G_BonusScreen(int32_t bonusonly) int32_t yy = 0, zz; gameHandleEvents(); - MUSIC_Update(); if (G_FPSLimit()) { diff --git a/source/duke3d/src/sector.cpp b/source/duke3d/src/sector.cpp index 7fd818867..72bd8f687 100644 --- a/source/duke3d/src/sector.cpp +++ b/source/duke3d/src/sector.cpp @@ -70,9 +70,10 @@ int A_CallSound(int sectNum, int spriteNum) if (spriteNum == -1) spriteNum = SFXsprite; + auto flags = S_GetUserFlags(soundNum); if (T1(SFXsprite) == 0) { - if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) != SF_GLOBAL) + if ((flags & (SF_GLOBAL|SF_DTAG)) != SF_GLOBAL) { if (soundNum) { @@ -93,7 +94,7 @@ int A_CallSound(int sectNum, int spriteNum) if (SHT(SFXsprite)) A_PlaySound(SHT(SFXsprite), spriteNum); - if ((g_sounds[soundNum].m & SF_LOOP) || (SHT(SFXsprite) && SHT(SFXsprite) != soundNum)) + if ((flags & SF_LOOP) || (SHT(SFXsprite) && SHT(SFXsprite) != soundNum)) S_StopEnvSound(soundNum, T6(SFXsprite)); T6(SFXsprite) = spriteNum; @@ -1465,7 +1466,9 @@ int P_ActivateSwitch(int playerNum, int wallOrSprite, int switchType) S_PlaySound3D(SWITCH_ON, (switchType == SWITCH_SPRITE) ? wallOrSprite : g_player[playerNum].ps->i, &davector); else if (hitag) { - if (switchType == SWITCH_SPRITE && (g_sounds[hitag].m & SF_TALK) == 0) + auto flags = S_GetUserFlags(hitag); + + if (switchType == SWITCH_SPRITE && (flags & SF_TALK) == 0) S_PlaySound3D(hitag, wallOrSprite, &davector); else A_PlaySound(hitag, g_player[playerNum].ps->i); @@ -1968,7 +1971,7 @@ void A_DamageObject_Duke3D(int spriteNum, int const dmgSrc) sprite[dmgSrc].xvel = (sprite[spriteNum].xvel>>1)+(sprite[spriteNum].xvel>>2); sprite[dmgSrc].ang -= (SA(spriteNum)<<1)+1024; SA(spriteNum) = getangle(SX(spriteNum)-sprite[dmgSrc].x,SY(spriteNum)-sprite[dmgSrc].y)-512; - if (g_sounds[POOLBALLHIT].num < 2) + if (S_CheckSoundPlaying(POOLBALLHIT) < 2) A_PlaySound(POOLBALLHIT, spriteNum); } else @@ -3022,11 +3025,7 @@ CHECKINV1: if (pPlayer->jetpack_on) { pPlayer->inven_icon = ICON_JETPACK; - if (pPlayer->scream_voice > FX_Ok) - { - FX_StopSound(pPlayer->scream_voice); - pPlayer->scream_voice = -1; - } + S_StopEnvSound(-1, pPlayer->i, CHAN_VOICE); #ifndef EDUKE32_STANDALONE if (!FURY) A_PlaySound(DUKE_JETPACK_ON,pPlayer->i); diff --git a/source/duke3d/src/sounds.cpp b/source/duke3d/src/sounds.cpp index 48949bdee..19ff7504b 100644 --- a/source/duke3d/src/sounds.cpp +++ b/source/duke3d/src/sounds.cpp @@ -1,10 +1,9 @@ //------------------------------------------------------------------------- /* Copyright (C) 2016 EDuke32 developers and contributors +Copyright (C) 2019 Christoph Oelckers -This file is part of EDuke32. - -EDuke32 is free software; you can redistribute it and/or +This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. @@ -25,99 +24,515 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "duke3d.h" -#include "renderlayer.h" // for win_gethwnd() -#include "al_midi.h" -#include "openaudio.h" #include "z_music.h" #include "mapinfo.h" -#include +#include "sound/s_soundinternal.h" BEGIN_DUKE_NS -#define DQSIZE 256 - -int32_t g_numEnvSoundsPlaying, g_highestSoundIdx; - -static char *MusicPtr; - -static int32_t MusicIsWaveform; -static int32_t MusicVoice = -1; - -static bool MusicPaused; -static bool SoundPaused; - -static std::atomic dnum, dq[DQSIZE]; -static mutex_t m_callback; - -static inline void S_SetProperties(assvoice_t *snd, int const owner, int const voice, int const dist, int const clock) +class DukeSoundEngine : public SoundEngine { - snd->owner = owner; - snd->id = voice; - snd->dist = dist; - snd->clock = clock; + // client specific parts of the sound engine go in this class. + void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan *chan) override; + TArray ReadSound(int lumpnum); + +public: + DukeSoundEngine() + { + S_Rolloff.RolloffType = ROLLOFF_Doom; // Seems like Duke uses the same rolloff type as Doom. + S_Rolloff.MinDistance = 144; // was originally 576 which looks like a bug and sounds like crap. + S_Rolloff.MaxDistance = 1088; + } +}; + +void S_InitSound() +{ + soundEngine = new DukeSoundEngine; } -void S_SoundStartup(void) +//========================================================================== +// +// +// +//========================================================================== + +TArray DukeSoundEngine::ReadSound(int lumpnum) { -#ifdef _WIN32 - void *initdata = (void *) win_gethwnd(); // used for DirectSound -#else - void *initdata = NULL; -#endif - - initprintf("Initializing sound... "); - - int status = FX_Init(snd_numvoices, snd_numchannels, snd_mixrate, initdata); - if (status != FX_Ok) - { - initprintf("failed! %s\n", FX_ErrorString(status)); - return; - } - - initprintf("%d voices, %d channels, 16-bit %d Hz\n", *snd_numvoices, *snd_numchannels, *snd_mixrate); - - for (int i = 0; i <= g_highestSoundIdx; ++i) - { - for (auto & voice : g_sounds[i].voices) - { - g_sounds[i].num = 0; - S_SetProperties(&voice, -1, 0, UINT16_MAX, 0); - } - } - - snd_fxvolume.Callback(); - - snd_reversestereo.Callback(); - FX_SetCallBack(S_Callback); - FX_SetPrintf(OSD_Printf); + auto wlump = fileSystem.OpenFileReader(lumpnum); + return wlump.Read(); } -void S_SoundShutdown(void) -{ - int status = FX_Shutdown(); - if (status != FX_Ok) - { - Bsprintf(tempbuf, "S_SoundShutdown(): error: %s", FX_ErrorString(status)); - G_GameExit(tempbuf); - } -} +//========================================================================== +// +// +// +//========================================================================== void S_PauseSounds(bool paused) { - if (SoundPaused == paused) - return; + soundEngine->SetPaused(paused); +} - SoundPaused = paused; +//========================================================================== +// +// +// +//========================================================================== - for (int i = 0; i <= g_highestSoundIdx; ++i) +void cacheAllSounds(void) +{ + auto& sfx = soundEngine->GetSounds(); + int i = 0; + for(auto &snd : sfx) { - for (auto & voice : g_sounds[i].voices) - if (voice.id > 0) - FX_PauseVoice(voice.id, paused); + soundEngine->CacheSound(&snd); + if (((++i)&31) == 0) + gameHandleEvents(); } } +//========================================================================== +// +// +// +//========================================================================== + +static inline int S_GetPitch(int num) +{ + auto const* snd = (sound_t*)soundEngine->GetUserData(num + 1); + if (!snd) return 0; + int const range = abs(snd->pitchEnd - snd->pitchStart); + + return (range == 0) ? snd->pitchStart : min(snd->pitchStart, snd->pitchEnd) + rand() % range; +} + +float S_ConvertPitch(int lpitch) +{ + return pow(2, lpitch / 1200.); // I hope I got this right that ASS uses a linear scale where 1200 is a full octave. +} + +int S_GetUserFlags(int num) +{ + auto const* snd = (sound_t*)soundEngine->GetUserData(num + 1); + if (!snd) return 0; + return snd->flags; +} + +//========================================================================== +// +// +// +//========================================================================== + +int S_DefineSound(unsigned index, const char *filename, int minpitch, int maxpitch, int priority, int type, int distance, float volume) +{ + if ((unsigned)index >= MAXSOUNDS) + return -1; + + auto& S_sfx = soundEngine->GetSounds(); + index++; + unsigned oldindex = S_sfx.Size(); + if (index >= S_sfx.Size()) + { + S_sfx.Resize(index + 1); + for (; oldindex <= index; oldindex++) + { + S_sfx[oldindex].Clear(); + } + } + auto sfx = &S_sfx[index]; + bool alreadydefined = !sfx->bTentative; + sfx->UserData.Resize(sizeof(sound_t)); + auto sndinf = (sound_t*)sfx->UserData.Data(); + sndinf->flags = type & ~SF_ONEINST_INTERNAL; + if (sndinf->flags & SF_LOOP) + sndinf->flags |= SF_ONEINST_INTERNAL; + + sfx->lumpnum = fileSystem.FindFile(filename); + sndinf->pitchStart = clamp(minpitch, INT16_MIN, INT16_MAX); + sndinf->pitchEnd = clamp(maxpitch, INT16_MIN, INT16_MAX); + sndinf->priority = priority & 255; + sndinf->volAdjust = clamp(distance, INT16_MIN, INT16_MAX); + sfx->Volume = volume; + sfx->NearLimit = 6; + sfx->bTentative = false; + sfx->name = filename; + return 0; +} + + +//========================================================================== +// +// +// +//========================================================================== + +static int S_CalcDistAndAng(int spriteNum, int soundNum, int sectNum, + const vec3_t *cam, const vec3_t *pos, int *distPtr, FVector3 *sndPos) +{ + // There's a lot of hackery going on here that could be mapped to rolloff and attenuation parameters. + // However, ultimately rolloff would also just reposition the sound source so this can remain as it is. + + int orgsndist = 0, sndang = 0, sndist = 0, explosion = 0; + auto const* snd = (sound_t*)soundEngine->GetUserData(soundNum+1); + int userflags = snd? snd->flags : 0; + int dist_adjust = snd? snd->volAdjust : 0; + + if (PN(spriteNum) != APLAYER || P_Get(spriteNum) != screenpeek) + { + orgsndist = sndist = FindDistance3D(cam->x - pos->x, cam->y - pos->y, (cam->z - pos->z)); + + if ((userflags & (SF_GLOBAL | SF_DTAG)) != SF_GLOBAL && S_IsAmbientSFX(spriteNum) && (sector[SECT(spriteNum)].lotag & 0xff) < 9) // ST_9_SLIDING_ST_DOOR + sndist = divscale14(sndist, SHT(spriteNum) + 1); + } + + sndist += dist_adjust; + if (sndist < 0) + sndist = 0; + + if (!FURY && sectNum > -1 && sndist && PN(spriteNum) != MUSICANDSFX + && !cansee(cam->x, cam->y, cam->z - (24 << 8), sectNum, SX(spriteNum), SY(spriteNum), SZ(spriteNum) - (24 << 8), SECT(spriteNum))) + sndist += sndist>>5; + + // Here the sound distance was clamped to a minimum of 144*4. + // It's better to handle rolloff in the backend instead of whacking the sound origin here. + // That way the lower end can be made customizable instead of losing all precision right here at the source. + if (sndist < 0) sndist = 0; + + if (distPtr) + { + *distPtr = sndist; + } + + if (sndPos) + { + FVector3 sndorg = GetSoundPos(pos); + FVector3 campos = GetSoundPos(cam); + // Now calculate the virtual position in sound system coordinates. + FVector3 sndvec = sndorg - campos; + if (orgsndist > 0) + { + float scale = float(sndist) / orgsndist; // adjust by what was calculated above; + *sndPos = campos + sndvec * scale; + } + else *sndPos = campos; + } + + return false; +} + +//========================================================================== +// +// +// +//========================================================================== + +void S_GetCamera(vec3_t** c, int32_t* ca, int32_t* cs) +{ + if (ud.camerasprite == -1) + { + if (ud.overhead_on != 2) + { + if (c) *c = &CAMERA(pos); + if (cs) *cs = CAMERA(sect); + if (ca) *ca = fix16_to_int(CAMERA(q16ang)); + } + else + { + auto pPlayer = g_player[screenpeek].ps; + if (c) *c = &pPlayer->pos; + if (cs) *cs = pPlayer->cursectnum; + if (ca) *ca = fix16_to_int(pPlayer->q16ang); + } + } + else + { + if (c) *c = &sprite[ud.camerasprite].pos; + if (cs) *cs = sprite[ud.camerasprite].sectnum; + if (ca) *ca = sprite[ud.camerasprite].ang; + } +} + +//========================================================================= +// +// CalcPosVel +// +// The game specific part of the sound updater. +// +//========================================================================= + +void DukeSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan* ) +{ + if (pos != nullptr) + { + vec3_t* campos; + int32_t camsect; + + S_GetCamera(&campos, nullptr, &camsect); + if (vel) vel->Zero(); + + if (type == SOURCE_Unattached) + { + pos->X = pt[0]; + pos->Y = pt[1]; + pos->Z = pt[2]; + } + else if (type == SOURCE_Actor) + { + auto actor = (spritetype*)source; + assert(actor != nullptr); + if (actor != nullptr) + { + S_CalcDistAndAng(int(actor - sprite), chanSound - 1, camsect, campos, &actor->pos, nullptr, pos); + /* + if (vel) // DN3D does not properly maintain this. + { + vel->X = float(actor->Vel.X * TICRATE); + vel->Y = float(actor->Vel.Z * TICRATE); + vel->Z = float(actor->Vel.Y * TICRATE); + } + */ + } + } + if ((chanflags & CHANF_LISTENERZ) && campos != nullptr && type != SOURCE_None) + { + pos->Y = campos->z / 256.f; + } + } +} + + +//========================================================================== +// +// +// +//========================================================================== + +void S_Update(void) +{ + SoundListener listener; + vec3_t* c; + int32_t ca, cs; + + S_GetCamera(&c, &ca, &cs); + + if (c != nullptr) + { + listener.angle = -(float)ca * pi::pi() / 1024; // Build uses a period of 2048. + listener.velocity.Zero(); + listener.position = GetSoundPos(c); + listener.underwater = false; + // This should probably use a real environment instead of the pitch hacking in S_PlaySound3D. + // listenactor->waterlevel == 3; + //assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber); + listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment; + listener.valid = true; + } + else + { + listener.angle = 0; + listener.position.Zero(); + listener.velocity.Zero(); + listener.underwater = false; + listener.Environment = nullptr; + listener.valid = false; + } + listener.ListenerObject = ud.camerasprite == -1 ? nullptr : &sprite[ud.camerasprite]; + soundEngine->SetListener(listener); + soundEngine->UpdateSounds((int)totalclock); +} + + +//========================================================================== +// +// +// +//========================================================================== + +int S_PlaySound3D(int num, int spriteNum, const vec3_t* pos, int channel, EChanFlags flags) +{ + int sndnum = VM_OnEventWithReturn(EVENT_SOUND, spriteNum, screenpeek, num); + + auto const pPlayer = g_player[myconnectindex].ps; + if (!soundEngine->isValidSoundId(sndnum+1) || !SoundEnabled() || (unsigned)spriteNum >= MAXSPRITES || (pPlayer->gm & MODE_MENU) || + (pPlayer->timebeforeexit > 0 && pPlayer->timebeforeexit <= GAMETICSPERSEC * 3)) return -1; + + int userflags = S_GetUserFlags(sndnum); + if ((!(snd_speech & 1) && (userflags & SF_TALK)) || ((userflags & SF_ADULT) && adult_lockout)) + return -1; + + // Duke talk + if (userflags & SF_TALK) + { + if ((g_netServer || ud.multimode > 1) && PN(spriteNum) == APLAYER && P_Get(spriteNum) != screenpeek) // other player sound + { + if ((snd_speech & 4) != 4) + return -1; + } + else if ((snd_speech & 1) != 1) + return -1; + + + bool foundone = soundEngine->EnumerateChannels([&](FSoundChan* chan) + { + auto sid = chan->OrgID; + auto flags = S_GetUserFlags(sid - 1); + return !!(flags & SF_TALK); + }); + // don't play if any Duke talk sounds are already playing + if (foundone) return -1; + } + else if ((userflags & (SF_DTAG | SF_GLOBAL)) == SF_DTAG) // Duke-Tag sound + { + return S_PlaySound(sndnum); + + } + + int32_t sndist; + FVector3 sndpos; // this is in sound engine space. + + vec3_t* campos; + int32_t camsect; + + S_GetCamera(&campos, nullptr, &camsect); + S_CalcDistAndAng(spriteNum, sndnum, camsect, campos, pos, &sndist, &sndpos); + int pitch = S_GetPitch(sndnum); + auto const pOther = g_player[screenpeek].ps; + + + if (pOther->sound_pitch) + pitch += pOther->sound_pitch; + + bool explosionp = ((userflags & (SF_GLOBAL | SF_DTAG)) == (SF_GLOBAL | SF_DTAG)) || ((!FURY) && (sndnum == PIPEBOMB_EXPLODE || sndnum == LASERTRIP_EXPLODE || sndnum == RPG_EXPLODE)); + + if (explosionp) + { + if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER) + pitch -= 1024; + } + else + { + if (sndist > 32767 && PN(spriteNum) != MUSICANDSFX && (userflags & (SF_LOOP | SF_MSFX)) == 0) + return -1; + + if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER + && (userflags & SF_TALK) == 0) + pitch = -768; + } + + bool is_playing = soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, sndnum+1); + if (is_playing && PN(spriteNum) != MUSICANDSFX) + S_StopEnvSound(sndnum, spriteNum); + + int const repeatp = (userflags & SF_LOOP); + + if (repeatp && (userflags & SF_ONEINST_INTERNAL) && is_playing) + { + return -1; + } + + // These explosion sounds originally used some distance hackery to make them louder but due to how the rolloff was set up they always played at full volume as a result. + // I think it is better to lower their attenuation so that they are louder than the rest but still fade in the distance. + // For the original effect, attenuation needs to be set to ATTN_NONE here. + float attenuation; + if (explosionp) attenuation = 0.5f; + else attenuation = (userflags & (SF_GLOBAL | SF_DTAG)) == SF_GLOBAL ? ATTN_NONE : ATTN_NORM; + + if (userflags & SF_LOOP) flags |= CHANF_LOOP; + auto chan = soundEngine->StartSound(SOURCE_Actor, &sprite[spriteNum], &sndpos, channel, flags, sndnum+1, attenuation == ATTN_NONE? 0.8f : 1.f, attenuation, nullptr, S_ConvertPitch(pitch)); + return chan ? 0 : -1; +} + +//========================================================================== +// +// +// +//========================================================================== + +int S_PlaySound(int num, int channel, EChanFlags flags) +{ + int sndnum = VM_OnEventWithReturn(EVENT_SOUND, g_player[screenpeek].ps->i, screenpeek, num); + + if (!soundEngine->isValidSoundId(sndnum+1) || !SoundEnabled()) return -1; + + int userflags = S_GetUserFlags(sndnum); + if ((!(snd_speech & 1) && (userflags & SF_TALK)) || ((userflags & SF_ADULT) && adult_lockout)) + return -1; + + int const pitch = S_GetPitch(sndnum); + + if (userflags & SF_LOOP) flags |= CHANF_LOOP; + auto chan = soundEngine->StartSound(SOURCE_None, nullptr, nullptr, channel, flags, sndnum + 1, 0.8f, ATTN_NONE, nullptr, S_ConvertPitch(pitch)); + return chan ? 0 : -1; +} + +//========================================================================== +// +// +// +//========================================================================== + +int A_PlaySound(int soundNum, int spriteNum, int channel, EChanFlags flags) +{ + return (unsigned)spriteNum >= MAXSPRITES ? S_PlaySound(soundNum, flags) : + S_PlaySound3D(soundNum, spriteNum, &sprite[spriteNum].pos, flags); +} + +void S_StopEnvSound(int sndNum, int sprNum, int channel) +{ + if (sprNum < -1 || sprNum >= MAXSPRITES) return; + + if (sprNum == -1) soundEngine->StopSoundID(sndNum+1); + else if (channel == -1) soundEngine->StopSound(SOURCE_Actor, &sprite[sprNum], -1, sndNum+1); + else soundEngine->StopSound(SOURCE_Actor, &sprite[sprNum], channel, -1); +} + +void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset) +{ + if (spriteNum < -1 || spriteNum >= MAXSPRITES) return; + double expitch = pow(2, pitchoffset / 1200.); // I hope I got this right that ASS uses a linear scale where 1200 is a full octave. + if (spriteNum == -1) + { + soundEngine->ChangeSoundPitch(SOURCE_Unattached, nullptr, CHAN_AUTO, expitch, soundNum+1); + } + else + { + soundEngine->ChangeSoundPitch(SOURCE_Actor, &sprite[spriteNum], CHAN_AUTO, expitch, soundNum+1); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +int A_CheckSoundPlaying(int spriteNum, int soundNum, int channel) +{ + if (spriteNum == -1) return soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, soundNum+1); + if ((unsigned)spriteNum >= MAXSPRITES) return false; + return soundEngine->IsSourcePlayingSomething(SOURCE_Actor, &sprite[spriteNum], channel, soundNum+1); +} + +// Check if actor is playing any sound. +int A_CheckAnySoundPlaying(int spriteNum) +{ + if ((unsigned)spriteNum >= MAXSPRITES) return false; + return soundEngine->IsSourcePlayingSomething(SOURCE_Actor, &sprite[spriteNum], CHAN_AUTO, 0); +} + +int S_CheckSoundPlaying(int soundNum) +{ + return soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, soundNum+1); +} + +//========================================================================== +// +// +// +//========================================================================== + void S_MenuSound(void) { static int SoundNum; @@ -131,11 +546,16 @@ void S_MenuSound(void) S_PlaySound(s); } +//========================================================================== +// +// Music +// +//========================================================================== static void S_SetMusicIndex(unsigned int m) { ud.music_episode = m / MAXLEVELS; - ud.music_level = m % MAXLEVELS; + ud.music_level = m % MAXLEVELS; } void S_PlayLevelMusicOrNothing(unsigned int m) @@ -147,8 +567,7 @@ void S_PlayLevelMusicOrNothing(unsigned int m) if (retval >= 0) { - // Thanks to scripting that stupid slot hijack cannot be refactored - but we'll store the real data elsewhere anyway! - auto &mr = m == USERMAPMUSICFAKESLOT ? userMapRecord : mapList[m]; + auto& mr = m == USERMAPMUSICFAKESLOT ? userMapRecord : mapList[m]; Mus_Play(mr.labelName, mr.music, true); S_SetMusicIndex(m); } @@ -156,7 +575,7 @@ void S_PlayLevelMusicOrNothing(unsigned int m) int S_TryPlaySpecialMusic(unsigned int m) { - auto &musicfn = mapList[m].music; + auto& musicfn = mapList[m].music; if (musicfn.IsNotEmpty()) { if (!Mus_Play(nullptr, musicfn, true)) @@ -182,539 +601,5 @@ void S_ContinueLevelMusic(void) VM_OnEvent(EVENT_CONTINUELEVELMUSICSLOT, g_player[myconnectindex].ps->i, myconnectindex); } -void S_Cleanup(void) -{ - static uint32_t ldnum = 0; - while (ldnum < dnum) - { - uint32_t num = dq[ldnum++ & (DQSIZE - 1)]; - - // negative index is RTS playback - if ((int32_t)num < 0) - { - continue; - } - - // num + (MAXSOUNDS*MAXSOUNDINSTANCES) is a sound played globally - // for which there was no open slot to keep track of the voice - if (num >= (MAXSOUNDS*MAXSOUNDINSTANCES)) - { - continue; - } - - int const voiceindex = num & (MAXSOUNDINSTANCES - 1); - - num = (num - voiceindex) / MAXSOUNDINSTANCES; - - auto &snd = g_sounds[num]; - auto &voice = snd.voices[voiceindex]; - - int const spriteNum = voice.owner; - - if (EDUKE32_PREDICT_FALSE(snd.num > MAXSOUNDINSTANCES)) - OSD_Printf(OSD_ERROR "S_Cleanup(): num exceeds MAXSOUNDINSTANCES! g_sounds[%d].num %d wtf?\n", num, snd.num); - else if (snd.num > 0) - --snd.num; - - // MUSICANDSFX uses t_data[0] to control restarting the sound - // CLEAR_SOUND_T0 - if (spriteNum != -1 && S_IsAmbientSFX(spriteNum) && sector[SECT(spriteNum)].lotag < 3) // ST_2_UNDERWATER - actor[spriteNum].t_data[0] = 0; - - S_SetProperties(&voice, -1, 0, UINT16_MAX, 0); - - } -} - -// returns number of bytes read -int32_t S_LoadSound(int num) -{ - if ((unsigned)num > (unsigned)g_highestSoundIdx || EDUKE32_PREDICT_FALSE(g_sounds[num].filename == NULL)) - return 0; - - auto &snd = g_sounds[num]; - - auto fp = S_OpenAudio(snd.filename, 0, 0); - - if (!fp.isOpen()) - { - OSD_Printf(OSDTEXT_RED "Sound %s(#%d) not found!\n", snd.filename, num); - return 0; - } - - int32_t l = fp.GetLength(); - snd.siz = l; - cacheAllocateBlock((intptr_t *)&snd.ptr, l, nullptr); - l = fp.Read(snd.ptr, l); - - return l; -} - -void cacheAllSounds(void) -{ - for (int i=0, j=0; i <= g_highestSoundIdx; ++i) - { - if (g_sounds[i].ptr == 0) - { - j++; - if ((j&7) == 0) - gameHandleEvents(); - - S_LoadSound(i); - } - } -} - -static inline int S_GetPitch(int num) -{ - auto const &snd = g_sounds[num]; - int const range = klabs(snd.pe - snd.ps); - - return (range == 0) ? snd.ps : min(snd.ps, snd.pe) + rand() % range; -} - -static int S_TakeSlot(int soundNum) -{ - S_Cleanup(); - - uint16_t dist = 0; - uint16_t clock = 0; - - int bestslot = 0; - int slot = 0; - - auto &snd = g_sounds[soundNum]; - - while (slot < MAXSOUNDINSTANCES && snd.voices[slot].id > 0) - { - auto &voice = snd.voices[slot]; - - if (voice.dist > dist || (voice.dist == dist && voice.clock > clock)) - { - clock = voice.clock; - dist = voice.dist; - - bestslot = slot; - } - - slot++; - } - - if (slot != MAXSOUNDINSTANCES) - return slot; - - if (FX_SoundActive(snd.voices[bestslot].id)) - FX_StopSound(snd.voices[bestslot].id); - - mutex_lock(&m_callback); - unative_t const ldnum = dnum; - dq[ldnum & (DQSIZE-1)] = (soundNum * MAXSOUNDINSTANCES) + bestslot; - dnum++; - mutex_unlock(&m_callback); - - S_Cleanup(); - - return bestslot; -} - -static int S_GetSlot(int soundNum) -{ - int slot = 0; - - while (slot < MAXSOUNDINSTANCES && g_sounds[soundNum].voices[slot].id > 0) - slot++; - - return slot == MAXSOUNDINSTANCES ? S_TakeSlot(soundNum) : slot; -} - -static inline int S_GetAngle(int ang, const vec3_t *cam, const vec3_t *pos) -{ - return (2048 + ang - getangle(cam->x - pos->x, cam->y - pos->y)) & 2047; -} - -static int S_CalcDistAndAng(int spriteNum, int soundNum, int sectNum, int angle, - const vec3_t *cam, const vec3_t *pos, int *distPtr, int *angPtr) -{ - int sndang = 0, sndist = 0, explosion = 0; - - if (PN(spriteNum) == APLAYER && P_Get(spriteNum) == screenpeek) - goto sound_further_processing; - - sndang = S_GetAngle(angle, cam, pos); - sndist = FindDistance3D(cam->x-pos->x, cam->y-pos->y, (cam->z-pos->z)); - - if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) != SF_GLOBAL && S_IsAmbientSFX(spriteNum) && (sector[SECT(spriteNum)].lotag&0xff) < 9) // ST_9_SLIDING_ST_DOOR - sndist = divscale14(sndist, SHT(spriteNum)+1); - -sound_further_processing: - sndist += g_sounds[soundNum].vo; - if (sndist < 0) - sndist = 0; - - if (!FURY && sectNum > -1 && sndist && PN(spriteNum) != MUSICANDSFX - && !cansee(cam->x, cam->y, cam->z - (24 << 8), sectNum, SX(spriteNum), SY(spriteNum), SZ(spriteNum) - (24 << 8), SECT(spriteNum))) - sndist += sndist>>5; - - if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) == (SF_GLOBAL|SF_DTAG)) - { -boost: - int const sdist = g_sounds[soundNum].vo > 0 ? g_sounds[soundNum].vo : 6144; - - explosion = true; - - if (sndist > sdist) - sndist = sdist; - } - else if (!FURY) - { - switch (DYNAMICSOUNDMAP(soundNum)) - { - case PIPEBOMB_EXPLODE__STATIC: - case LASERTRIP_EXPLODE__STATIC: - case RPG_EXPLODE__STATIC: - goto boost; - } - } - - if ((g_sounds[soundNum].m & (SF_GLOBAL|SF_DTAG)) == SF_GLOBAL || sndist < ((255-LOUDESTVOLUME) << 6)) - sndist = ((255-LOUDESTVOLUME) << 6); - - *distPtr = sndist; - *angPtr = sndang; - - return explosion; -} - -int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) -{ - int32_t j = VM_OnEventWithReturn(EVENT_SOUND, spriteNum, screenpeek, num); - - if ((j == -1 && num != -1) || !SoundEnabled()) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn) - return -1; - - int const sndNum = j; - sound_t & snd = g_sounds[sndNum]; - - if (EDUKE32_PREDICT_FALSE((unsigned) sndNum > (unsigned) g_highestSoundIdx || snd.filename == NULL || snd.ptr == NULL)) - { - OSD_Printf("WARNING: invalid sound #%d\n", num); - return -1; - } - - auto const pPlayer = g_player[myconnectindex].ps; - - if (((snd.m & SF_ADULT) && adult_lockout) || (unsigned)spriteNum >= MAXSPRITES || (pPlayer->gm & MODE_MENU) || !FX_VoiceAvailable(snd.pr) - || (pPlayer->timebeforeexit > 0 && pPlayer->timebeforeexit <= GAMETICSPERSEC * 3)) - return -1; - - // Duke talk - if (snd.m & SF_TALK) - { - if ((g_netServer || ud.multimode > 1) && PN(spriteNum) == APLAYER && P_Get(spriteNum) != screenpeek) // other player sound - { - if ((snd_speech & 4) != 4) - return -1; - } - else if ((snd_speech & 1) != 1) - return -1; - - // don't play if any Duke talk sounds are already playing - for (j = 0; j <= g_highestSoundIdx; ++j) - if ((g_sounds[j].m & SF_TALK) && g_sounds[j].num > 0) - return -1; - } - else if ((snd.m & (SF_DTAG|SF_GLOBAL)) == SF_DTAG) // Duke-Tag sound - { - int const voice = S_PlaySound(sndNum); - - if (voice <= FX_Ok) - return -1; - - j = 0; - while (j < MAXSOUNDINSTANCES && snd.voices[j].id != voice) - j++; - - - snd.voices[j].owner = spriteNum; - - return voice; - } - - int32_t sndist, sndang; - int const explosionp = S_CalcDistAndAng(spriteNum, sndNum, CAMERA(sect), fix16_to_int(CAMERA(q16ang)), &CAMERA(pos), pos, &sndist, &sndang); - int pitch = S_GetPitch(sndNum); - auto const pOther = g_player[screenpeek].ps; - - - if (pOther->sound_pitch) - pitch += pOther->sound_pitch; - - if (explosionp) - { - if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER) - pitch -= 1024; - } - else - { - if (sndist > 32767 && PN(spriteNum) != MUSICANDSFX && (snd.m & (SF_LOOP|SF_MSFX)) == 0) - return -1; - - if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER - && (snd.m & SF_TALK) == 0) - pitch = -768; - } - - if (snd.num > 0 && PN(spriteNum) != MUSICANDSFX) - S_StopEnvSound(sndNum, spriteNum); - - int const sndSlot = S_GetSlot(sndNum); - - if (sndSlot >= MAXSOUNDINSTANCES) - { - return -1; - } - - int const repeatp = (snd.m & SF_LOOP); - - if (repeatp && (snd.m & SF_ONEINST_INTERNAL) && snd.num > 0) - { - return -1; - } - - int const voice = FX_Play3D(snd.ptr, snd.siz, repeatp ? FX_LOOP : FX_ONESHOT, pitch, sndang >> 4, sndist >> 6, - snd.pr, snd.volume, (sndNum * MAXSOUNDINSTANCES) + sndSlot); - - if (voice <= FX_Ok) - { - return -1; - } - - snd.num++; - - S_SetProperties(&snd.voices[sndSlot], spriteNum, voice, sndist >> 6, 0); - - return voice; -} - -int S_PlaySound(int num) -{ - int sndnum = VM_OnEventWithReturn(EVENT_SOUND, g_player[screenpeek].ps->i, screenpeek, num); - - if ((sndnum == -1 && num != -1) || !SoundEnabled()) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn) - return -1; - - num = sndnum; - - sound_t & snd = g_sounds[num]; - - if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_highestSoundIdx || snd.filename == NULL || snd.ptr == NULL)) - { - OSD_Printf("WARNING: invalid sound #%d\n",num); - return -1; - } - - if ((!(snd_speech & 1) && (snd.m & SF_TALK)) || ((snd.m & SF_ADULT) && adult_lockout) || !FX_VoiceAvailable(snd.pr)) - return -1; - - int const pitch = S_GetPitch(num); - - sndnum = S_GetSlot(num); - - if (sndnum >= MAXSOUNDINSTANCES) - { - return -1; - } - - int const voice = (snd.m & SF_LOOP) ? FX_Play(snd.ptr, snd.siz, 0, -1, pitch, LOUDESTVOLUME, LOUDESTVOLUME, - LOUDESTVOLUME, snd.siz, snd.volume, (num * MAXSOUNDINSTANCES) + sndnum) - : FX_Play3D(snd.ptr, snd.siz, FX_ONESHOT, pitch, 0, 255 - LOUDESTVOLUME, snd.pr, snd.volume, - (num * MAXSOUNDINSTANCES) + sndnum); - - if (voice <= FX_Ok) - { - return -1; - } - - snd.num++; - S_SetProperties(&snd.voices[sndnum], -1, voice, 255-LOUDESTVOLUME, 0); - - return voice; -} - -int A_PlaySound(int soundNum, int spriteNum) -{ - if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) - return -1; - - return (unsigned)spriteNum >= MAXSPRITES ? S_PlaySound(soundNum) : - S_PlaySound3D(soundNum, spriteNum, &sprite[spriteNum].pos); -} - -void S_StopEnvSound(int sndNum, int sprNum) -{ - if (EDUKE32_PREDICT_FALSE((unsigned)sndNum > (unsigned)g_highestSoundIdx) || g_sounds[sndNum].num <= 0) - return; - - int j; - - do - { - for (j=0; j FX_Ok) || (sprNum != -1 && voice.owner == sprNum)) - { - if (voice.id > FX_Ok) - { - if (FX_SoundActive(voice.id)) - FX_StopSound(voice.id); - break; - } - } - } - } - while (j < MAXSOUNDINSTANCES); -} - -// Do not remove this or make it inline. -void S_StopAllSounds(void) -{ - FX_StopAllSounds(); -} - -void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset) -{ - if ((unsigned)soundNum > (unsigned)g_highestSoundIdx || g_sounds[soundNum].num <= 0) - return; - - for (auto &voice : g_sounds[soundNum].voices) - { - if ((spriteNum == -1 && voice.id > FX_Ok) || (spriteNum != -1 && voice.owner == spriteNum)) - { - if (EDUKE32_PREDICT_FALSE(spriteNum >= 0 && voice.id <= FX_Ok)) - initprintf(OSD_ERROR "S_ChangeSoundPitch(): bad voice %d for sound ID %d!\n", voice.id, soundNum); - else if (voice.id > FX_Ok && FX_SoundActive(voice.id)) - FX_SetPitch(voice.id, pitchoffset); - break; - } - } -} - -void S_Update(void) -{ - if ((g_player[myconnectindex].ps->gm & (MODE_GAME|MODE_DEMO)) == 0) - return; - - g_numEnvSoundsPlaying = 0; - - const vec3_t *c; - int32_t ca,cs; - - if (ud.camerasprite == -1) - { - if (ud.overhead_on != 2) - { - c = &CAMERA(pos); - cs = CAMERA(sect); - ca = fix16_to_int(CAMERA(q16ang)); - } - else - { - auto pPlayer = g_player[screenpeek].ps; - c = &pPlayer->pos; - cs = pPlayer->cursectnum; - ca = fix16_to_int(pPlayer->q16ang); - } - } - else - { - c = &sprite[ud.camerasprite].pos; - cs = sprite[ud.camerasprite].sectnum; - ca = sprite[ud.camerasprite].ang; - } - - int sndnum = 0; - int const highest = g_highestSoundIdx; - - do - { - if (g_sounds[sndnum].num == 0) - continue; - - S_Cleanup(); - - for (auto &voice : g_sounds[sndnum].voices) - { - int const spriteNum = voice.owner; - - if ((unsigned)spriteNum >= MAXSPRITES || voice.id <= FX_Ok || !FX_SoundActive(voice.id)) - continue; - - int sndist, sndang; - - S_CalcDistAndAng(spriteNum, sndnum, cs, ca, c, (const vec3_t *)&sprite[spriteNum], &sndist, &sndang); - - if (S_IsAmbientSFX(spriteNum)) - g_numEnvSoundsPlaying++; - - // AMBIENT_SOUND - FX_Pan3D(voice.id, sndang >> 4, sndist >> 6); - voice.dist = sndist >> 6; - voice.clock++; - } - } while (++sndnum <= highest); -} - -// S_Callback() can be called from either the audio thread when a sound ends, or the main thread -// when playing back a new sound needs an existing sound to be stopped first -void S_Callback(intptr_t num) -{ - if ((int32_t)num == MUSIC_ID) - return; - - mutex_lock(&m_callback); - unative_t const ldnum = dnum; - dq[ldnum & (DQSIZE - 1)] = (uint32_t)num; - dnum++; - mutex_unlock(&m_callback); -} - -int A_CheckSoundPlaying(int spriteNum, int soundNum) -{ - if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return 0; - - if (g_sounds[soundNum].num > 0 && spriteNum >= 0) - { - for (auto &voice : g_sounds[soundNum].voices) - if (voice.owner == spriteNum) - return 1; - } - - return (spriteNum == -1) ? (g_sounds[soundNum].num != 0) : 0; -} - -// Check if actor is playing any sound. -int A_CheckAnySoundPlaying(int spriteNum) -{ - int const msp = g_highestSoundIdx; - - for (int j = 0; j <= msp; ++j) - { - for (auto &voice : g_sounds[j].voices) - if (voice.owner == spriteNum) - return 1; - } - - return 0; -} - -int S_CheckSoundPlaying(int soundNum) -{ - if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return false; - return (g_sounds[soundNum].num != 0); -} END_DUKE_NS diff --git a/source/duke3d/src/sounds.h b/source/duke3d/src/sounds.h index 428815125..9693f031e 100644 --- a/source/duke3d/src/sounds.h +++ b/source/duke3d/src/sounds.h @@ -30,45 +30,27 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define sounds_public_h_ #include "sounds_common.h" +#include "sound/s_soundinternal.h" #include "z_music.h" BEGIN_DUKE_NS // KEEPINSYNC lunatic/con_lang.lua #define MAXSOUNDS 4096 -#define MAXSOUNDINSTANCES 8 #define LOUDESTVOLUME 111 -#define MUSIC_ID -65536 typedef struct { - int16_t owner; - int16_t id; - uint16_t dist; - uint16_t clock; -} assvoice_t; - -typedef struct -{ - char * ptr, *filename; // 8b/16b - int32_t length, num, siz; // 12b - float volume; // 4b - assvoice_t voices[MAXSOUNDINSTANCES]; // 64b - int16_t ps, pe, vo; // 6b - char pr, m; // 2b + int pitchStart, pitchEnd, volAdjust; + int priority, flags; } sound_t; -extern sound_t g_sounds[MAXSOUNDS]; -extern int32_t g_numEnvSoundsPlaying,g_highestSoundIdx; - -int A_CheckSoundPlaying(int spriteNum,int soundNum); -int A_PlaySound(int soundNum, int spriteNum); +int A_CheckSoundPlaying(int spriteNum, int soundNum, int channel = 0); +int A_PlaySound(int soundNum, int spriteNum, int channel = CHAN_AUTO, EChanFlags flags = 0); void S_Callback(intptr_t num); int A_CheckAnySoundPlaying(int spriteNum); int S_CheckSoundPlaying(int soundNum); -void S_Cleanup(void); inline void S_ClearSoundLocks(void) {} -int32_t S_LoadSound(uint32_t num); void cacheAllSounds(void); void S_MenuSound(void); void S_PauseMusic(bool paused); @@ -77,14 +59,15 @@ void S_PlayLevelMusicOrNothing(unsigned int); int S_TryPlaySpecialMusic(unsigned int); void S_PlaySpecialMusicOrNothing(unsigned int); void S_ContinueLevelMusic(void); -int S_PlaySound(int num); -int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos); -void S_SoundShutdown(void); -void S_SoundStartup(void); -void S_StopEnvSound(int sndNum,int sprNum); +int S_PlaySound(int num, int channel = CHAN_AUTO, EChanFlags flags = 0); +int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos, int channel = CHAN_AUTO, EChanFlags flags = 0); +void S_StopEnvSound(int sndNum,int sprNum, int flags = -1); void S_StopAllSounds(void); void S_Update(void); void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset); +int S_GetUserFlags(int sndnum); +int S_DefineSound(unsigned index, const char* filename, int ps, int pe, int pr, int m, int vo, float vol); +void S_InitSound(); static inline bool S_IsAmbientSFX(int spriteNum) { diff --git a/source/mact/gpl-2.0.txt b/source/mact/gpl-2.0.txt deleted file mode 100644 index d159169d1..000000000 --- a/source/mact/gpl-2.0.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/source/mact/include/_control.h b/source/mact/include/_control.h deleted file mode 100644 index b3198bf09..000000000 --- a/source/mact/include/_control.h +++ /dev/null @@ -1,173 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 1996, 2003 - 3D Realms Entertainment - -This file is NOT part of Duke Nukem 3D version 1.5 - Atomic Edition -However, it is either an older version of a file that is, or is -some test code written during the development of Duke Nukem 3D. -This file is provided purely for educational interest. - -Duke Nukem 3D is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms -*/ -//------------------------------------------------------------------------- - -//**************************************************************************** -// -// Private header for CONTROL.C -// -//**************************************************************************** - -#pragma once - -#ifndef control_private_h_ -#define control_private_h_ - -#include "compat.h" -#include "keyboard.h" - - -//**************************************************************************** -// -// DEFINES -// -//**************************************************************************** - -#define AXISUNDEFINED 0x7f -#define BUTTONUNDEFINED 0x7f -#define KEYUNDEFINED 0x7f - -#define THRESHOLD (0x200 * 32767 / 10000) -#define MINTHRESHOLD (0x80 * 32767 / 10000) - -#define DEFAULTMOUSESENSITIVITY 4 // 0x7000+MINIMUMMOUSESENSITIVITY - -#define INSTANT_ONOFF 0 -#define TOGGLE_ONOFF 1 - -#define MAXCONTROLVALUE 0x7fff - -// Number of Mouse buttons - -//#define MAXMOUSEBUTTONS 10 - -// Number of JOY buttons -// KEEPINSYNC duke3d/src/gamedefs.h, build/src/sdlayer.cpp -#define MAXJOYBUTTONS 32 -#define MAXJOYBUTTONSANDHATS (MAXJOYBUTTONS+4) - -// Number of JOY axes -// KEEPINSYNC duke3d/src/gamedefs.h, build/src/sdlayer.cpp -#define MAXJOYAXES 9 -#define MAXJOYDIGITAL (MAXJOYAXES*2) - -// NORMAL axis scale -#define NORMALAXISSCALE 65536 - -#define LIMITCONTROL(x) (*x = clamp(*x, -MAXCONTROLVALUE, MAXCONTROLVALUE)) - -//**************************************************************************** -// -// TYPEDEFS -// -//**************************************************************************** - -typedef enum -{ - motion_Left = -1, - motion_Up = -1, - motion_None = 0, - motion_Right = 1, - motion_Down = 1 -} motion; - - -typedef struct -{ - int32_t joyMinX; - int32_t joyMinY; - int32_t threshMinX; - int32_t threshMinY; - int32_t threshMaxX; - int32_t threshMaxY; - int32_t joyMaxX; - int32_t joyMaxY; - int32_t joyMultXL; - int32_t joyMultYL; - int32_t joyMultXH; - int32_t joyMultYH; -} JoystickDef; - -// int32_t ThrottleMin; -// int32_t RudderMin; -// int32_t ThrottlethreshMin; -// int32_t RudderthreshMin; -// int32_t ThrottlethreshMax; -// int32_t RudderthreshMax; -// int32_t ThrottleMax; -// int32_t RudderMax; -// int32_t ThrottleMultL; -// int32_t RudderMultL; -// int32_t ThrottleMultH; -// int32_t RudderMultH; - - -typedef struct -{ - uint8_t active; - uint8_t used; - uint8_t toggle; - uint8_t buttonheld; - int32_t cleared; -} controlflags; - -typedef struct -{ - kb_scancode key1; - kb_scancode key2; -} controlkeymaptype; - -typedef struct -{ - uint8_t singleclicked; - uint8_t doubleclicked; - uint16_t extra; -} controlbuttontype; - -typedef struct -{ - uint8_t analogmap; - uint8_t minmap; - uint8_t maxmap; - uint8_t extra; -} controlaxismaptype; - -typedef struct -{ - int32_t analog; - int8_t digital; - int8_t digitalClearedN, digitalClearedP; -} controlaxistype; - - -//*************************************************************************** -// -// PROTOTYPES -// -//*************************************************************************** - -#endif diff --git a/source/mact/include/control.h b/source/mact/include/control.h deleted file mode 100644 index 9756bed4c..000000000 --- a/source/mact/include/control.h +++ /dev/null @@ -1,169 +0,0 @@ -//------------------------------------------------------------------------- -/* -Copyright (C) 1996, 2003 - 3D Realms Entertainment - -This file is part of Duke Nukem 3D version 1.5 - Atomic Edition - -Duke Nukem 3D is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -Original Source: 1996 - Todd Replogle -Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms -Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) -*/ -//------------------------------------------------------------------------- - -//*************************************************************************** -// -// Public header for CONTROL.C. -// -//*************************************************************************** - -#pragma once - -#ifndef control_public_h_ -#define control_public_h_ - -#include "tarray.h" -#include "inputstate.h" - -//*************************************************************************** -// -// DEFINES -// -//*************************************************************************** - -//*************************************************************************** -// -// TYPEDEFS -// -//*************************************************************************** -typedef enum - { - axis_up, - axis_down, - axis_left, - axis_right - } axisdirection; - -typedef enum - { - analog_turning=0, - analog_strafing=1, - analog_lookingupanddown=2, - analog_elevation=3, - analog_rolling=4, - analog_moving=5, - analog_maxtype - } analogcontrol; - -typedef enum - { - controltype_keyboard, - controltype_keyboardandmouse, - controltype_keyboardandjoystick - } controltype; - -typedef enum - { - controldevice_keyboard, - controldevice_mouse, - controldevice_joystick - } controldevice; - -enum GameControllerButton : int -{ - GAMECONTROLLER_BUTTON_INVALID = -1, - GAMECONTROLLER_BUTTON_A, - GAMECONTROLLER_BUTTON_B, - GAMECONTROLLER_BUTTON_X, - GAMECONTROLLER_BUTTON_Y, - GAMECONTROLLER_BUTTON_BACK, - GAMECONTROLLER_BUTTON_GUIDE, - GAMECONTROLLER_BUTTON_START, - GAMECONTROLLER_BUTTON_LEFTSTICK, - GAMECONTROLLER_BUTTON_RIGHTSTICK, - GAMECONTROLLER_BUTTON_LEFTSHOULDER, - GAMECONTROLLER_BUTTON_RIGHTSHOULDER, - GAMECONTROLLER_BUTTON_DPAD_UP, - GAMECONTROLLER_BUTTON_DPAD_DOWN, - GAMECONTROLLER_BUTTON_DPAD_LEFT, - GAMECONTROLLER_BUTTON_DPAD_RIGHT, - GAMECONTROLLER_BUTTON_MAX -}; - -enum GameControllerAxis : int -{ - GAMECONTROLLER_AXIS_INVALID = -1, - GAMECONTROLLER_AXIS_LEFTX, - GAMECONTROLLER_AXIS_LEFTY, - GAMECONTROLLER_AXIS_RIGHTX, - GAMECONTROLLER_AXIS_RIGHTY, - GAMECONTROLLER_AXIS_TRIGGERLEFT, - GAMECONTROLLER_AXIS_TRIGGERRIGHT, - GAMECONTROLLER_AXIS_MAX -}; - -enum class LastSeenInput : unsigned char -{ - Keyboard, - Joystick, -}; - -//*************************************************************************** -// -// GLOBALS -// -//*************************************************************************** - -extern bool CONTROL_Started; -extern bool CONTROL_MousePresent; -extern bool CONTROL_JoyPresent; -extern bool CONTROL_MouseEnabled; -extern bool CONTROL_JoystickEnabled; - -extern LastSeenInput CONTROL_LastSeenInput; - - -//*************************************************************************** -// -// PROTOTYPES -// -//*************************************************************************** -void CONTROL_ClearAssignments( void ); -void CONTROL_GetInput( ControlInfo *info ); - -bool CONTROL_Startup(controltype which, int32_t ( *TimeFunction )( void ), int32_t ticspersecond); -void CONTROL_Shutdown( void ); - -void CONTROL_MapAnalogAxis(int whichaxis, int whichanalog, controldevice device); -void CONTROL_MapDigitalAxis(int32_t whichaxis, int32_t whichfunction, int32_t direction, controldevice device); -void CONTROL_SetAnalogAxisScale(int32_t whichaxis, int32_t axisscale, controldevice device); -void CONTROL_SetAnalogAxisInvert(int32_t whichaxis, int32_t invert, controldevice device); - -void CONTROL_ScanForControllers(void); - -int32_t CONTROL_GetGameControllerDigitalAxisPos(int32_t axis); -int32_t CONTROL_GetGameControllerDigitalAxisNeg(int32_t axis); -void CONTROL_ClearGameControllerDigitalAxisPos(int32_t axis); -void CONTROL_ClearGameControllerDigitalAxisNeg(int32_t axis); - - -////////// KEY/MOUSE BIND STUFF ////////// - - -//////////////////// - -#endif diff --git a/source/mact/include/joystick.h b/source/mact/include/joystick.h deleted file mode 100644 index 5696ae52e..000000000 --- a/source/mact/include/joystick.h +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef __joystick_h -#define __joystick_h - - - -#define HAT_CENTERED 0x00 -#define HAT_UP 0x01 -#define HAT_RIGHT 0x02 -#define HAT_DOWN 0x04 -#define HAT_LEFT 0x08 -#define HAT_RIGHTUP (HAT_RIGHT|HAT_UP) -#define HAT_RIGHTDOWN (HAT_RIGHT|HAT_DOWN) -#define HAT_LEFTUP (HAT_LEFT|HAT_UP) -#define HAT_LEFTDOWN (HAT_LEFT|HAT_DOWN) - -int32_t JOYSTICK_GetButtons( void ); -int32_t JOYSTICK_GetGameControllerButtons( void ); -int32_t JOYSTICK_ClearButton( int32_t b ); -void JOYSTICK_ClearGameControllerButton( int32_t b ); -void JOYSTICK_ClearAllButtons( void ); - -int32_t JOYSTICK_GetHat( int32_t h ); -void JOYSTICK_ClearHat( int32_t h ); -void JOYSTICK_ClearAllHats( void ); - -int32_t JOYSTICK_GetAxis( int32_t a ); -void JOYSTICK_ClearAxis( int32_t a ); -void JOYSTICK_ClearAllAxes( void ); - -#endif /* __joystick_h */ diff --git a/source/mact/include/mouse.h b/source/mact/include/mouse.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/source/mact/src/control.cpp b/source/mact/src/control.cpp deleted file mode 100644 index 6eb85ce87..000000000 --- a/source/mact/src/control.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/* - * control.c - * MACT library controller handling - * - * Derived from MACT386.LIB disassembly by Jonathon Fowler - * - */ - -#include "_control.h" -#include "baselayer.h" -#include "compat.h" -#include "control.h" -#include "joystick.h" -#include "keyboard.h" -#include "mouse.h" -#include "osd.h" -#include "gamecvars.h" -#include "pragmas.h" - -bool CONTROL_Started = false; -bool CONTROL_MouseEnabled = false; -bool CONTROL_MousePresent = false; -bool CONTROL_JoyPresent = false; -bool CONTROL_JoystickEnabled = false; - -LastSeenInput CONTROL_LastSeenInput; - -static int32_t CONTROL_NumMouseButtons = 0; -static int32_t CONTROL_NumJoyButtons = 0; -static int32_t CONTROL_NumJoyAxes = 0; - -// static controlkeymaptype CONTROL_KeyMapping[CONTROL_NUM_FLAGS]; - -static controlaxismaptype CONTROL_JoyAxesMap[MAXJOYAXES]; -static controlaxistype CONTROL_JoyAxes[MAXJOYAXES]; -static controlaxistype CONTROL_LastJoyAxes[MAXJOYAXES]; -static int32_t CONTROL_JoyAxesScale[MAXJOYAXES]; -static int8_t CONTROL_JoyAxesInvert[MAXJOYAXES]; - -static controlbuttontype CONTROL_JoyButtonMapping[MAXJOYBUTTONS]; - -static int32_t CONTROL_JoyButtonClicked[MAXJOYBUTTONS]; -static int32_t CONTROL_JoyButtonClickedState[MAXJOYBUTTONS]; -static int32_t CONTROL_JoyButtonClickedTime[MAXJOYBUTTONS]; -static int32_t CONTROL_JoyButtonState[MAXJOYBUTTONS]; -static uint8_t CONTROL_JoyButtonClickedCount[MAXJOYBUTTONS]; - -static int32_t(*ExtGetTime)(void); -//static int32_t ticrate; -static uint8_t CONTROL_DoubleClickSpeed; - -int32_t CONTROL_ButtonFlags[NUMKEYS]; -bool CONTROL_BindsEnabled = 0; - -#define CONTROL_CheckRange(which) ((unsigned)which >= (unsigned)NUMKEYS) - -static int32_t CONTROL_GetTime(void) -{ - static int32_t t = 0; - t += 5; - return t; -} - -void CONTROL_MapAnalogAxis(int whichaxis, int whichanalog, controldevice device) -{ - controlaxismaptype *set; - - if ((unsigned)whichanalog >= (unsigned)analog_maxtype && whichanalog != -1) - { - //Error("CONTROL_MapAnalogAxis: analog function %d out of valid range for %d analog functions.", - // whichanalog, analog_maxtype); - return; - } - - switch (device) - { - case controldevice_joystick: - if ((unsigned)whichaxis >= (unsigned)MAXJOYAXES) - { - //Error("CONTROL_MapAnalogAxis: axis %d out of valid range for %d joystick axes.", - // whichaxis, MAXJOYAXES); - return; - } - - set = CONTROL_JoyAxesMap; - break; - - default: - //Error("CONTROL_MapAnalogAxis: invalid controller device type"); - return; - } - - set[whichaxis].analogmap = whichanalog; -} - -void CONTROL_SetAnalogAxisScale(int32_t whichaxis, int32_t axisscale, controldevice device) -{ - int32_t *set; - - switch (device) - { - case controldevice_joystick: - if ((unsigned) whichaxis >= (unsigned) MAXJOYAXES) - { - //Error("CONTROL_SetAnalogAxisScale: axis %d out of valid range for %d joystick axes.", - // whichaxis, MAXJOYAXES); - return; - } - - set = CONTROL_JoyAxesScale; - break; - - default: - //Error("CONTROL_SetAnalogAxisScale: invalid controller device type"); - return; - } - - set[whichaxis] = axisscale; -} - -void CONTROL_SetAnalogAxisInvert(int32_t whichaxis, int32_t invert, controldevice device) -{ - int8_t * set; - - switch (device) - { - case controldevice_joystick: - if ((unsigned) whichaxis >= (unsigned) MAXJOYAXES) - { - //Error("CONTROL_SetAnalogAxisInvert: axis %d out of valid range for %d joystick axes.", - // whichaxis, MAXJOYAXES); - return; - } - - set = CONTROL_JoyAxesInvert; - break; - - default: - //Error("CONTROL_SetAnalogAxisInvert: invalid controller device type"); - return; - } - - set[whichaxis] = invert; -} - -void CONTROL_MapDigitalAxis(int32_t whichaxis, int32_t whichfunction, int32_t direction, controldevice device) -{ - controlaxismaptype *set; - - if (CONTROL_CheckRange(whichfunction)) whichfunction = AXISUNDEFINED; - - switch (device) - { - case controldevice_joystick: - if ((unsigned) whichaxis >= (unsigned) MAXJOYAXES) - { - //Error("CONTROL_MapDigitalAxis: axis %d out of valid range for %d joystick axes.", - // whichaxis, MAXJOYAXES); - return; - } - - set = CONTROL_JoyAxesMap; - break; - - default: - //Error("CONTROL_MapDigitalAxis: invalid controller device type"); - return; - } - - switch (direction) // JBF: this is all very much a guess. The ASM puzzles me. - { - case axis_up: - case axis_left: - set[whichaxis].minmap = whichfunction; - break; - case axis_down: - case axis_right: - set[whichaxis].maxmap = whichfunction; - break; - default: - break; - } -} - -void CONTROL_ClearAssignments(void) -{ - memset(CONTROL_JoyAxes, 0, sizeof(CONTROL_JoyAxes)); - memset(CONTROL_JoyAxesInvert, 0, sizeof(CONTROL_JoyAxesInvert)); - memset(CONTROL_JoyAxesMap, AXISUNDEFINED, sizeof(CONTROL_JoyAxesMap)); - memset(CONTROL_JoyButtonMapping, BUTTONUNDEFINED, sizeof(CONTROL_JoyButtonMapping)); - memset(CONTROL_LastJoyAxes, 0, sizeof(CONTROL_LastJoyAxes)); -} - -static int DoGetDeviceButtons( - int32_t buttons, int32_t tm, - int32_t NumButtons, - int32_t *DeviceButtonState, - int32_t *ButtonClickedTime, - int32_t *ButtonClickedState, - int32_t *ButtonClicked, - uint8_t *ButtonClickedCount -) -{ - int32_t i=NumButtons-1; - int retval = 0; - - for (; i>=0; i--) - { - int const bs = (buttons >> i) & 1; - - DeviceButtonState[i] = bs; - ButtonClickedState[i] = FALSE; - - if (bs) - { - retval = 1; - - if (ButtonClicked[i] == FALSE) - { - ButtonClicked[i] = TRUE; - - if (ButtonClickedCount[i] == 0 || tm > ButtonClickedTime[i]) - { - ButtonClickedTime[i] = tm + CONTROL_DoubleClickSpeed; - ButtonClickedCount[i] = 1; - } - else if (tm < ButtonClickedTime[i]) - { - ButtonClickedState[i] = TRUE; - ButtonClickedTime[i] = 0; - ButtonClickedCount[i] = 2; - } - } - else if (ButtonClickedCount[i] == 2) - { - ButtonClickedState[i] = TRUE; - } - - continue; - } - - if (ButtonClickedCount[i] == 2) - ButtonClickedCount[i] = 0; - - ButtonClicked[i] = FALSE; - } - - return retval; -} - -static void CONTROL_GetDeviceButtons(void) -{ - int32_t const t = ExtGetTime(); - - if (CONTROL_JoystickEnabled) - { - int retval = DoGetDeviceButtons( - JOYSTICK_GetButtons(), t, - CONTROL_NumJoyButtons, - CONTROL_JoyButtonState, - CONTROL_JoyButtonClickedTime, - CONTROL_JoyButtonClickedState, - CONTROL_JoyButtonClicked, - CONTROL_JoyButtonClickedCount - ); - if (retval) - CONTROL_LastSeenInput = LastSeenInput::Joystick; - } -} - -static int CONTROL_DigitizeAxis(int axis, controldevice device) -{ - controlaxistype *set, *lastset; - - switch (device) - { - case controldevice_joystick: - set = CONTROL_JoyAxes; - lastset = CONTROL_LastJoyAxes; - break; - - default: return 0; - } - - set[axis].digitalClearedN = lastset[axis].digitalClearedN; - set[axis].digitalClearedP = lastset[axis].digitalClearedP; - - if (set[axis].analog > 0) - { - set[axis].digitalClearedN = 0; - - if (set[axis].analog > THRESHOLD || (set[axis].analog > MINTHRESHOLD && lastset[axis].digital == 1)) - set[axis].digital = 1; - else - set[axis].digitalClearedP = 0; - - return 1; - } - else if (set[axis].analog < 0) - { - set[axis].digitalClearedP = 0; - - if (set[axis].analog < -THRESHOLD || (set[axis].analog < -MINTHRESHOLD && lastset[axis].digital == -1)) - set[axis].digital = -1; - else - set[axis].digitalClearedN = 0; - - return 1; - } - else - { - set[axis].digitalClearedN = 0; - set[axis].digitalClearedP = 0; - } - - return 0; -} - -static void CONTROL_ScaleAxis(int axis, controldevice device) -{ - controlaxistype *set; - int32_t *scale; - int8_t * invert; - - switch (device) - { - case controldevice_joystick: - set = CONTROL_JoyAxes; - scale = CONTROL_JoyAxesScale; - invert = CONTROL_JoyAxesInvert; - break; - - default: return; - } - - int const invertResult = !!invert[axis]; - set[axis].analog = (mulscale16(set[axis].analog, scale[axis]) ^ -invertResult) + invertResult; -} - -static void CONTROL_ApplyAxis(int axis, ControlInfo *info, controldevice device) -{ - controlaxistype *set; - controlaxismaptype *map; - - switch (device) - { - case controldevice_joystick: - set = CONTROL_JoyAxes; - map = CONTROL_JoyAxesMap; - break; - - default: return; - } - - switch (map[axis].analogmap) - { - case analog_turning: info->dyaw += set[axis].analog; break; - case analog_strafing: info->dx += set[axis].analog; break; - case analog_lookingupanddown: info->dpitch += set[axis].analog; break; - case analog_elevation: info->dy += set[axis].analog; break; - case analog_rolling: info->droll += set[axis].analog; break; - case analog_moving: info->dz += set[axis].analog; break; - default: break; - } -} - -static void CONTROL_PollDevices(ControlInfo *info) -{ - memset(info, 0, sizeof(ControlInfo)); - - if (CONTROL_MouseEnabled) - inputState.GetMouseDelta(info); - - if (CONTROL_JoystickEnabled) - { - Bmemcpy(CONTROL_LastJoyAxes, CONTROL_JoyAxes, sizeof(CONTROL_JoyAxes)); - memset(CONTROL_JoyAxes, 0, sizeof(CONTROL_JoyAxes)); - - for (int i=joystick.numAxes-1; i>=0; i--) - { - CONTROL_JoyAxes[i].analog = joystick.pAxis[i]; - - if (CONTROL_DigitizeAxis(i, controldevice_joystick)) - CONTROL_LastSeenInput = LastSeenInput::Joystick; - CONTROL_ScaleAxis(i, controldevice_joystick); - LIMITCONTROL(&CONTROL_JoyAxes[i].analog); - CONTROL_ApplyAxis(i, info, controldevice_joystick); - } - } - - CONTROL_GetDeviceButtons(); -} - -static int CONTROL_HandleAxisFunction(int32_t *p1, controlaxistype *axes, controlaxismaptype *axismap, int numAxes) -{ - int axis = numAxes - 1; - int retval = 0; - - do - { - if (!axes[axis].digital) - continue; - - int const j = (axes[axis].digital < 0) ? axismap[axis].minmap : axismap[axis].maxmap; - - if (j != AXISUNDEFINED) - { - p1[j] = 1; - retval = 1; - } - } - while (axis--); - - return retval; -} - -static void CONTROL_AxisFunctionState(int32_t *p1) -{ - if (CONTROL_NumJoyAxes) - { - if (CONTROL_HandleAxisFunction(p1, CONTROL_JoyAxes, CONTROL_JoyAxesMap, CONTROL_NumJoyAxes)) - CONTROL_LastSeenInput = LastSeenInput::Joystick; - } -} - -static void CONTROL_ButtonFunctionState(int32_t *p1) -{ - if (CONTROL_NumJoyButtons) - { - int i=CONTROL_NumJoyButtons-1, j; - int retval = 0; - - do - { - j = CONTROL_JoyButtonMapping[i].doubleclicked; - if (j != KEYUNDEFINED) - { - auto const state = CONTROL_JoyButtonClickedState[i]; - p1[j] |= state; - retval |= state; - } - - j = CONTROL_JoyButtonMapping[i].singleclicked; - if (j != KEYUNDEFINED) - { - auto const state = CONTROL_JoyButtonState[i]; - p1[j] |= state; - retval |= state; - } - } - while (i--); - - if (retval) - CONTROL_LastSeenInput = LastSeenInput::Joystick; - } -} - -int32_t CONTROL_GetGameControllerDigitalAxisPos(int32_t axis) -{ - if (!joystick.isGameController) - return 0; - - return CONTROL_JoyAxes[axis].digital > 0 && !CONTROL_JoyAxes[axis].digitalClearedP; -} -int32_t CONTROL_GetGameControllerDigitalAxisNeg(int32_t axis) -{ - if (!joystick.isGameController) - return 0; - - return CONTROL_JoyAxes[axis].digital < 0 && !CONTROL_JoyAxes[axis].digitalClearedN; -} - -void CONTROL_ClearGameControllerDigitalAxisPos(int32_t axis) -{ - if (!joystick.isGameController) - return; - - CONTROL_JoyAxes[axis].digitalClearedP = 1; -} -void CONTROL_ClearGameControllerDigitalAxisNeg(int32_t axis) -{ - if (!joystick.isGameController) - return; - - CONTROL_JoyAxes[axis].digitalClearedN = 1; -} - - -static void CONTROL_GetFunctionInput(void) -{ - CONTROL_ButtonFunctionState(CONTROL_ButtonFlags); - CONTROL_AxisFunctionState(CONTROL_ButtonFlags); -} - -void CONTROL_GetInput(ControlInfo *info) -{ - CONTROL_PollDevices(info); - CONTROL_GetFunctionInput(); - inputchecked = 1; -} - -static void CONTROL_ResetJoystickValues() -{ - CONTROL_NumJoyAxes = min(MAXJOYAXES, joystick.numAxes); - CONTROL_NumJoyButtons = min(MAXJOYBUTTONS, joystick.numButtons + 4 * (joystick.numHats > 0)); - CONTROL_JoystickEnabled = CONTROL_JoyPresent = !!((inputdevices & 4) >> 2); -} - -void CONTROL_ScanForControllers() -{ - joyScanDevices(); - CONTROL_ResetJoystickValues(); -} - -bool CONTROL_Startup(controltype which, int32_t(*TimeFunction)(void), int32_t ticspersecond) -{ - UNREFERENCED_PARAMETER(which); - - if (CONTROL_Started) return false; - - ExtGetTime = TimeFunction ? TimeFunction : CONTROL_GetTime; - - // what the fuck??? - CONTROL_DoubleClickSpeed = (ticspersecond * 57) / 100; - - if (CONTROL_DoubleClickSpeed <= 0) - CONTROL_DoubleClickSpeed = 1; - - if (initinput()) - return true; - - CONTROL_NumMouseButtons = MAXMOUSEBUTTONS; - mouseInit(); - CONTROL_MousePresent = ((inputdevices & 2) == 2); - CONTROL_MouseEnabled = CONTROL_MousePresent; - - CONTROL_ResetJoystickValues(); - - CONTROL_Started = TRUE; - - return false; -} - -void CONTROL_Shutdown(void) -{ - if (!CONTROL_Started) - return; - - mouseUninit(); - uninitinput(); - - CONTROL_Started = FALSE; -} - diff --git a/source/mact/src/joystick.cpp b/source/mact/src/joystick.cpp deleted file mode 100644 index 4f2da88f3..000000000 --- a/source/mact/src/joystick.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * joystick.c - * MACT library -to- Build Port Joystick Glue - * - * by Hendricks266 - * - * We needed raw joystick access for the Wii port. - * We only had raw mouse and keyboard access. - * I made raw joystick access. - * - */ -//------------------------------------------------------------------------- -/* -Duke Nukem Copyright (C) 1996, 2003 3D Realms Entertainment - -This file is part of Duke Nukem 3D version 1.5 - Atomic Edition - -Duke Nukem 3D is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -//------------------------------------------------------------------------- - -#include "compat.h" - -#include "joystick.h" -#include "baselayer.h" - -#include "keyboard.h" -#include "_control.h" - -int32_t JOYSTICK_GetButtons(void) -{ - int32_t buttons; - - joyReadButtons(&buttons); - - if (joystick.numHats > 0) - { - int32_t hat = JOYSTICK_GetHat(0); - if (hat != 0) - buttons |= hat << min(MAXJOYBUTTONS, joystick.numButtons); - } - - return buttons; -} -int32_t JOYSTICK_GetGameControllerButtons(void) -{ - if (!joystick.isGameController) - return 0; - - int32_t buttons; - joyReadButtons(&buttons); - return buttons; -} -int32_t JOYSTICK_ClearButton(int32_t b) -{ - return (joystick.bits &= ~b); -} -void JOYSTICK_ClearGameControllerButton(int32_t b) -{ - if (!joystick.isGameController) - return; - - joystick.bits &= ~b; -} -void JOYSTICK_ClearAllButtons(void) -{ - joystick.bits = 0; -} - -int32_t JOYSTICK_GetHat(int32_t h) -{ - if (h>=0 && h=0 && h=0 && a=0 && a= spriteHitag && T1(spriteNum) == 1) { FX_SetReverb(0); - FX_SetReverbDelay(0); T1(spriteNum) = 0; } } else if (pSprite->lotag < 999 && (unsigned)sector[pSprite->sectnum].lotag < 9 && // ST_9_SLIDING_ST_DOOR snd_ambience && sector[SECT(spriteNum)].floorz != sector[SECT(spriteNum)].ceilingz) { - if (g_sounds[pSprite->lotag].m & SF_MSFX) + auto flags = S_GetUserFlags(pSprite->lotag); + if (flags & SF_MSFX) { int playerDist = dist(&sprite[pPlayer->i], pSprite); @@ -1372,11 +1372,10 @@ ACTOR_STATIC void G_MoveFX(void) } #endif - if (playerDist < spriteHitag && T1(spriteNum) == 0 && FX_VoiceAvailable(g_sounds[pSprite->lotag].pr-1)) + if (playerDist < spriteHitag && T1(spriteNum) == 0)// && FX_VoiceAvailable(g_sounds[pSprite->lotag].pr-1)) { // Start playing an ambience sound. - - char om = g_sounds[pSprite->lotag].m; +#if 0 // let the sound system handle this internally. if (g_numEnvSoundsPlaying == snd_numvoices) { int32_t j; @@ -1392,10 +1391,8 @@ ACTOR_STATIC void G_MoveFX(void) if (j == -1) goto next_sprite; } - - g_sounds[pSprite->lotag].m |= SF_LOOP; - A_PlaySound(pSprite->lotag,spriteNum); - g_sounds[pSprite->lotag].m = om; +#endif + A_PlaySound(pSprite->lotag, spriteNum, CHAN_AUTO, CHANF_LOOP); T1(spriteNum) = 1; // AMBIENT_SFX_PLAYING } else if (playerDist >= spriteHitag && T1(spriteNum) == 1) @@ -1408,7 +1405,7 @@ ACTOR_STATIC void G_MoveFX(void) } } - if (g_sounds[pSprite->lotag].m & SF_GLOBAL) + if ((flags & (SF_GLOBAL | SF_DTAG)) == SF_GLOBAL) { // Randomly playing global sounds (flyby of planes, screams, ...) diff --git a/source/rr/src/anim.cpp b/source/rr/src/anim.cpp index 9496492cb..8053a7cb8 100644 --- a/source/rr/src/anim.cpp +++ b/source/rr/src/anim.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "renderlayer.h" #include "duke3d.h" #include "animlib.h" -#include "mouse.h" #include "compat.h" #include "input.h" @@ -397,7 +396,7 @@ int32_t Anim_Play(const char *fn) if (sound == -1) FX_StopAllSounds(); else - S_PlaySound(sound); + S_PlaySound(sound, CHAN_AUTO, CHANF_UI); soundidx++; } @@ -411,7 +410,7 @@ int32_t Anim_Play(const char *fn) if (sound == -1) FX_StopAllSounds(); else - S_PlaySound(sound); + S_PlaySound(sound, CHAN_AUTO, CHANF_UI); soundidx++; } @@ -567,7 +566,7 @@ int32_t Anim_Play(const char *fn) if (sound == -1) FX_StopAllSounds(); else - S_PlaySound(sound); + S_PlaySound(sound, CHAN_AUTO, CHANF_UI); soundidx++; } diff --git a/source/rr/src/config.cpp b/source/rr/src/config.cpp index e46e80aa9..351874c8e 100644 --- a/source/rr/src/config.cpp +++ b/source/rr/src/config.cpp @@ -62,20 +62,13 @@ void CONFIG_SetDefaults(void) ScreenBPP = 32; g_player[0].ps->aim_mode = 1; ud.config.ShowOpponentWeapons = 0; - ud.althud = 1; ud.automsg = 0; ud.camerasprite = -1; ud.camera_time = 0;//4; - ud.menu_slidebarz = 65536; - ud.menu_slidebarmargin = RR ? 6 * 65536 : 65536; - ud.menu_slidecursorz = RR ? 32768 : 65536; - ud.runkey_mode = 0; - ud.screen_size = 4; ud.screen_tilting = 1; ud.statusbarflags = STATUSBAR_NOSHRINK; - ud.statusbarmode = 1; ud.statusbarscale = 100; playerteam = 0; ud.angleinterpolation = 0; @@ -88,9 +81,6 @@ void CONFIG_SetDefaults(void) ud.menubackground = 1; ud.slidebar_paldisabled = 1; ud.shadow_pal = 4; - ud.menu_scrollbartilenum = -1; - ud.menu_scrollbarz = 65536; - ud.menu_scrollcursorz = 65536; } diff --git a/source/rr/src/d_menu.cpp b/source/rr/src/d_menu.cpp index d275f62fb..d2af6d069 100644 --- a/source/rr/src/d_menu.cpp +++ b/source/rr/src/d_menu.cpp @@ -361,15 +361,15 @@ void GameInterface::MenuSound(EMenuSounds snd) switch (snd) { case CursorSound: - S_PlaySound(RR ? 335 : KICK_HIT); + S_PlaySound(RR ? 335 : KICK_HIT, CHAN_AUTO, CHANF_UI); break; case AdvanceSound: - S_PlaySound(RR? 341 : PISTOL_BODYHIT); + S_PlaySound(RR? 341 : PISTOL_BODYHIT, CHAN_AUTO, CHANF_UI); break; case CloseSound: - S_PlaySound(EXITMENUSOUND); + S_PlaySound(EXITMENUSOUND, CHAN_AUTO, CHANF_UI); break; default: @@ -443,7 +443,16 @@ void GameInterface::StartGame(FGameStartup& gs) } ud.m_player_skill = gs.Skill + 1; - if (menu_sounds) g_skillSoundVoice = S_PlaySound(skillsound); + if (menu_sounds && skillsound >= 0 && SoundEnabled()) + { + S_PlaySound(skillsound, CHAN_AUTO, CHANF_UI); + + while (S_CheckSoundPlaying(skillsound)) + { + S_Update(); + G_HandleAsync(); + } + } ud.m_respawn_monsters = (gs.Skill == 3); ud.m_monsters_off = ud.monsters_off = 0; ud.m_respawn_items = 0; diff --git a/source/rr/src/duke3d.h b/source/rr/src/duke3d.h index d64e30770..b5b3eed2d 100644 --- a/source/rr/src/duke3d.h +++ b/source/rr/src/duke3d.h @@ -27,11 +27,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "a.h" #include "baselayer.h" #include "build.h" -#include "cache1d.h" + #include "compat.h" -#include "fx_man.h" -#include "keyboard.h" #include "pragmas.h" #include "polymost.h" @@ -115,7 +113,6 @@ END_RR_NS #include "actors.h" #include "common_game.h" #include "config.h" -#include "control.h" #include "gamecontrol.h" #include "game.h" #include "gamedef.h" @@ -125,7 +122,6 @@ END_RR_NS #include "global.h" #include "inv.h" #include "macros.h" -#include "music.h" #include "namesdyn.h" #include "net.h" #include "player.h" diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index d7b1a3336..ab84e5699 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------- +//------------------------------------------------------------------------- /* Copyright (C) 2016 EDuke32 developers and contributors @@ -160,6 +160,12 @@ enum gametokens T_TEXTUREFILTER, }; +static void gameTimerHandler(void) +{ + S_Update(); + G_HandleSpecialKeys(); +} + void G_HandleSpecialKeys(void) { // we need CONTROL_GetInput in order to pick up joystick button presses @@ -5940,16 +5946,15 @@ void G_InitTimer(int32_t ticspersec) static int32_t g_RTSPlaying; // Returns: started playing? -extern int G_StartRTS(int lumpNum, int localPlayer) +int G_StartRTS(int lumpNum, int localPlayer) { if (!adult_lockout && SoundEnabled() && RTS_IsInitialized() && g_RTSPlaying == 0 && (snd_speech & (localPlayer ? 1 : 4))) { - char *const pData = (char *)RTS_GetSound(lumpNum - 1); - - if (pData != NULL) + auto sid = RTS_GetSoundID(lumpNum - 1); + if (sid != -1) { - FX_Play3D(pData, RTS_SoundLength(lumpNum - 1), FX_ONESHOT, 0, 0, 1, 255, 1.f, -lumpNum); + S_PlaySound(sid, CHAN_AUTO, CHANF_UI); g_RTSPlaying = 7; return 1; } @@ -6038,7 +6043,7 @@ void G_HandleLocalKeys(void) { if (G_ChangeHudLayout(1)) { - S_PlaySound(RR ? 341 : THUD); + S_PlaySound(RR ? 341 : THUD, CHAN_AUTO, CHANF_UI); } } else @@ -6057,7 +6062,7 @@ void G_HandleLocalKeys(void) { if (G_ChangeHudLayout(-1)) { - S_PlaySound(RR ? 341 : THUD); + S_PlaySound(RR ? 341 : THUD, CHAN_AUTO, CHANF_UI); } } else @@ -6303,43 +6308,6 @@ void G_HandleLocalKeys(void) } } -static int32_t S_DefineAudioIfSupported(char **fn, const char *name) -{ -#if !defined HAVE_FLAC || !defined HAVE_VORBIS - const char *extension = Bstrrchr(name, '.'); -# if !defined HAVE_FLAC - if (extension && !Bstrcasecmp(extension, ".flac")) - return -2; -# endif -# if !defined HAVE_VORBIS - if (extension && !Bstrcasecmp(extension, ".ogg")) - return -2; -# endif -#endif - realloc_copy(fn, name); - return 0; -} - -static int32_t S_DefineSound(int sndidx, const char *name, int minpitch, int maxpitch, int priority, int type, int distance, float volume) -{ - if ((unsigned)sndidx >= MAXSOUNDS || S_DefineAudioIfSupported(&g_sounds[sndidx].filename, name)) - return -1; - - auto &snd = g_sounds[sndidx]; - - snd.ps = clamp(minpitch, INT16_MIN, INT16_MAX); - snd.pe = clamp(maxpitch, INT16_MIN, INT16_MAX); - snd.pr = priority & 255; - snd.m = type & ~SF_ONEINST_INTERNAL; - snd.vo = clamp(distance, INT16_MIN, INT16_MAX); - snd.volume = volume; - - if (snd.m & SF_LOOP) - snd.m |= SF_ONEINST_INTERNAL; - - return 0; -} - // Returns: // 0: all OK // -1: ID declaration was invalid: @@ -6773,7 +6741,7 @@ int loaddefinitions_game(const char *fileName, int32_t firstPass) if (pScript) parsedefinitions_game(pScript, firstPass); - for (auto& m : *userConfig.AddDefs) + if (userConfig.AddDefs) for (auto& m : *userConfig.AddDefs) parsedefinitions_game_include(m, NULL, "null", firstPass); if (pScript) @@ -6808,10 +6776,6 @@ static void G_Cleanup(void) Bfree(g_player[i].inputBits); } - for (i=MAXSOUNDS-1; i>=0; i--) - { - Bfree(g_sounds[i].filename); - } if (label != (char *)&sprite[0]) Bfree(label); if (labelcode != (int32_t *)§or[0]) Bfree(labelcode); Bfree(apScript); @@ -6835,8 +6799,6 @@ static void G_Cleanup(void) void G_Shutdown(void) { - S_SoundShutdown(); - CONTROL_Shutdown(); G_SetFog(0); engineUnInit(); G_Cleanup(); @@ -7076,6 +7038,7 @@ static void G_Startup(void) set_memerr_handler(&G_HandleMemErr); timerInit(TICRATE); + timerSetCallback(gameTimerHandler); G_CompileScripts(); @@ -7298,6 +7261,8 @@ int GameInterface::app_main() { I_Error("app_main: There was a problem initializing the Build engine: %s\n", engineerrstr); } + hud_size.Callback(); + S_InitSound(); g_logFlushWindow = 0; @@ -7479,7 +7444,6 @@ int GameInterface::app_main() } videoSetPalette(0, g_player[myconnectindex].ps->palette, 0); - S_SoundStartup(); } // check if the minifont will support lowercase letters (3136-3161) @@ -7605,60 +7569,66 @@ MAIN_LOOP_RESTART: else #endif { - MUSIC_Update(); G_HandleLocalKeys(); } OSD_DispatchQueued(); + static bool frameJustDrawn; char gameUpdate = false; double const gameUpdateStartTime = timerGetHiTicks(); if (((g_netClient || g_netServer) || !(g_player[myconnectindex].ps->gm & (MODE_MENU|MODE_DEMO))) && totalclock >= ototalclock+TICSPERFRAME) { - //if (g_networkMode != NET_DEDICATED_SERVER) - //{ - // if (RRRA && g_player[myconnectindex].ps->on_motorcycle) - // P_GetInputMotorcycle(myconnectindex); - // else if (RRRA && g_player[myconnectindex].ps->on_boat) - // P_GetInputBoat(myconnectindex); - // else - // P_GetInput(myconnectindex); - //} - - //Bmemcpy(&inputfifo[0][myconnectindex], &localInput, sizeof(input_t)); - - S_Update(); - do { - if (ready2send == 0) break; - Net_GetInput(); + //if (g_networkMode != NET_DEDICATED_SERVER) + //{ + // if (RRRA && g_player[myconnectindex].ps->on_motorcycle) + // P_GetInputMotorcycle(myconnectindex); + // else if (RRRA && g_player[myconnectindex].ps->on_boat) + // P_GetInputBoat(myconnectindex); + // else + // P_GetInput(myconnectindex); + //} - ototalclock += TICSPERFRAME; + //Bmemcpy(&inputfifo[0][myconnectindex], &localInput, sizeof(input_t)); - int const moveClock = (int) totalclock; + if (!frameJustDrawn) + break; - if (((ud.show_help == 0 && !GUICapture && (g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU) || ud.recstat == 2 || (g_netServer || ud.multimode > 1)) && - (g_player[myconnectindex].ps->gm&MODE_GAME)) - { - G_MoveLoop(); - } + frameJustDrawn = false; - if (totalclock - moveClock >= TICSPERFRAME) - { - // computing a tic takes longer than a tic, so we're slowing - // the game down. rather than tightly spinning here, go draw - // a frame since we're fucked anyway - break; - } - } - while (((g_netClient || g_netServer) || !(g_player[myconnectindex].ps->gm & (MODE_MENU|MODE_DEMO))) && totalclock >= ototalclock+TICSPERFRAME); + do + { + if (ready2send == 0) break; + Net_GetInput(); - gameUpdate = true; - g_gameUpdateTime = timerGetHiTicks()-gameUpdateStartTime; - if (g_gameUpdateAvgTime < 0.f) - g_gameUpdateAvgTime = g_gameUpdateTime; - g_gameUpdateAvgTime = ((GAMEUPDATEAVGTIMENUMSAMPLES-1.f)*g_gameUpdateAvgTime+g_gameUpdateTime)/((float) GAMEUPDATEAVGTIMENUMSAMPLES); + ototalclock += TICSPERFRAME; + + int const moveClock = (int) totalclock; + + if (((ud.show_help == 0 && !GUICapture && (g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU) || ud.recstat == 2 || (g_netServer || ud.multimode > 1)) && + (g_player[myconnectindex].ps->gm&MODE_GAME)) + { + G_MoveLoop(); + } + + if (totalclock - moveClock >= TICSPERFRAME) + { + // computing a tic takes longer than a tic, so we're slowing + // the game down. rather than tightly spinning here, go draw + // a frame since we're fucked anyway + break; + } + } + while (((g_netClient || g_netServer) || !(g_player[myconnectindex].ps->gm & (MODE_MENU|MODE_DEMO))) && totalclock >= ototalclock+TICSPERFRAME); + + gameUpdate = true; + g_gameUpdateTime = timerGetHiTicks()-gameUpdateStartTime; + if (g_gameUpdateAvgTime < 0.f) + g_gameUpdateAvgTime = g_gameUpdateTime; + g_gameUpdateAvgTime = ((GAMEUPDATEAVGTIMENUMSAMPLES-1.f)*g_gameUpdateAvgTime+g_gameUpdateTime)/((float) GAMEUPDATEAVGTIMENUMSAMPLES); + } while(0); } G_DoCheats(); @@ -7690,6 +7660,8 @@ MAIN_LOOP_RESTART: { g_gameUpdateAndDrawTime = g_beforeSwapTime/* timerGetHiTicks()*/ - gameUpdateStartTime; } + + frameJustDrawn = true; } if (g_player[myconnectindex].ps->gm&MODE_DEMO) diff --git a/source/rr/src/game.h b/source/rr/src/game.h index cc4d938f0..5660e5e61 100644 --- a/source/rr/src/game.h +++ b/source/rr/src/game.h @@ -143,13 +143,11 @@ typedef struct { int32_t camera_time,folfvel,folavel,folx,foly,fola; int32_t reccnt; - int32_t runkey_mode,statusbarscale,weaponswitch; // JBF 20031125 + int32_t statusbarscale,weaponswitch; // JBF 20031125 int32_t statusbarmode; int32_t noexits,automsg; int32_t althud; int32_t statusbarflags, statusbarrange; - int32_t menu_slidebarz, menu_slidebarmargin, menu_slidecursorz; - int32_t menu_scrollbartilenum, menu_scrollbarz, menu_scrollcursorz; int32_t entered_name,screen_tilting; int32_t coop,screen_size,lockout,crosshair; @@ -199,6 +197,9 @@ extern user_defs ud; extern const char *s_buildDate; extern char boardfilename[BMAX_PATH]; +#define USERMAPMUSICFAKEVOLUME MAXVOLUMES +#define USERMAPMUSICFAKELEVEL (MAXLEVELS-1) +#define USERMAPMUSICFAKESLOT ((USERMAPMUSICFAKEVOLUME * MAXLEVELS) + USERMAPMUSICFAKELEVEL) static inline int G_HaveUserMap(void) { diff --git a/source/rr/src/gamedef.cpp b/source/rr/src/gamedef.cpp index 219c23bac..dae444e17 100644 --- a/source/rr/src/gamedef.cpp +++ b/source/rr/src/gamedef.cpp @@ -945,6 +945,7 @@ static inline void C_FinishBitOr(int32_t value) static int32_t C_ParseCommand(int32_t loop) { int32_t i, j=0, k=0, tw; + TArray buffer; do { @@ -1940,8 +1941,8 @@ static int32_t C_ParseCommand(int32_t loop) C_SkipSpace(); - TArray buffer; - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) + buffer.Clear(); + while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) { buffer.Push(*textptr); textptr++; @@ -1951,77 +1952,68 @@ static int32_t C_ParseCommand(int32_t loop) continue; } case CON_DEFINESOUND: + { + int ps, pe, vo, pr, m; + g_scriptPtr--; C_GetNextValue(LABEL_DEFINE); // Ideally we could keep the value of i from C_GetNextValue() instead of having to hash_find() again. // This depends on tempbuf remaining in place after C_GetNextValue(): - j = hash_find(&h_labels,tempbuf); + j = hash_find(&h_labels, tempbuf); - k = *(g_scriptPtr-1); - if (EDUKE32_PREDICT_FALSE((unsigned)k >= MAXSOUNDS-1)) + k = g_scriptPtr[-1]; + if ((unsigned)k >= MAXSOUNDS - 1) { - initprintf("%s:%d: error: index exceeds sound limit of %d.\n",g_scriptFileName,g_lineNumber, MAXSOUNDS-1); + initprintf("%s:%d: error: sound index exceeds limit of %d.\n", g_scriptFileName, g_lineNumber, MAXSOUNDS - 1); g_errorCnt++; - k = MAXSOUNDS-1; + k = MAXSOUNDS - 1; } + /*else if (g_sounds[k].filename != NULL) + { + initprintf("%s:%d: warning: sound %d already defined (%s)\n", g_scriptFileName, g_lineNumber, k, g_sounds[k].filename); + g_warningCnt++; + }*/ + g_scriptPtr--; i = 0; C_SkipComments(); - if (g_sounds[k].filename == NULL) - g_sounds[k].filename = (char *)Xcalloc(BMAX_PATH,sizeof(uint8_t)); + buffer.Clear(); if (*textptr == '\"') { textptr++; while (*textptr && *textptr != '\"') { - g_sounds[k].filename[i++] = *textptr++; - if (EDUKE32_PREDICT_FALSE(i >= BMAX_PATH-1)) - { - initprintf("%s:%d: error: sound filename exceeds limit of %d characters.\n",g_scriptFileName,g_lineNumber,BMAX_PATH-1); - g_errorCnt++; - C_SkipComments(); - break; - } + buffer.Push(*textptr++); } textptr++; } else while (*textptr != ' ' && *textptr != '\t' && *textptr != '\r' && *textptr != '\n') { - g_sounds[k].filename[i++] = *textptr++; - if (EDUKE32_PREDICT_FALSE(i >= BMAX_PATH-1)) - { - initprintf("%s:%d: error: sound filename exceeds limit of %d characters.\n",g_scriptFileName,g_lineNumber,BMAX_PATH-1); - g_errorCnt++; - C_SkipComments(); - break; - } + buffer.Push(*textptr++); } - g_sounds[k].filename[i] = '\0'; + buffer.Push(0); C_GetNextValue(LABEL_DEFINE); - g_sounds[k].ps = *(g_scriptPtr-1); + ps = g_scriptPtr[-1]; C_GetNextValue(LABEL_DEFINE); - g_sounds[k].pe = *(g_scriptPtr-1); + pe = g_scriptPtr[-1]; C_GetNextValue(LABEL_DEFINE); - g_sounds[k].pr = *(g_scriptPtr-1); + pr = g_scriptPtr[-1]; C_GetNextValue(LABEL_DEFINE); - g_sounds[k].m = *(g_scriptPtr-1) & ~SF_ONEINST_INTERNAL; - if (*(g_scriptPtr-1) & SF_LOOP) - g_sounds[k].m |= SF_ONEINST_INTERNAL; + m = g_scriptPtr[-1]; C_GetNextValue(LABEL_DEFINE); - g_sounds[k].vo = *(g_scriptPtr-1); + vo = g_scriptPtr[-1]; g_scriptPtr -= 5; - g_sounds[k].volume = 1.f; + int res = S_DefineSound(k, buffer.Data(), ps, pe, pr, m, vo, 1.f); - if (k > g_highestSoundIdx) - g_highestSoundIdx = k; continue; + } case CON_ENDA: if (EDUKE32_PREDICT_FALSE(!g_parsingActorPtr)) @@ -2252,7 +2244,7 @@ void C_Compile(const char *fileName) C_ParseCommand(1); - for (FString & m : *userConfig.AddCons.get()) + if (userConfig.AddCons) for (FString & m : *userConfig.AddCons.get()) { C_Include(m); } diff --git a/source/rr/src/global.h b/source/rr/src/global.h index 28c900642..be920e86d 100644 --- a/source/rr/src/global.h +++ b/source/rr/src/global.h @@ -246,7 +246,6 @@ G_EXTERN input_t inputfifo[MOVEFIFOSIZ][MAXPLAYERS]; G_EXTERN int32_t g_noEnemies; G_EXTERN int32_t g_restorePalette; G_EXTERN int32_t g_screenCapture; -G_EXTERN sound_t g_sounds[MAXSOUNDS]; G_EXTERN uint32_t everyothertime; G_EXTERN uint32_t g_moveThingsCount; G_EXTERN double g_gameUpdateTime; diff --git a/source/rr/src/net.cpp b/source/rr/src/net.cpp index 993283e75..f46f7cd9a 100644 --- a/source/rr/src/net.cpp +++ b/source/rr/src/net.cpp @@ -1802,7 +1802,7 @@ void Net_GetInput(void) if (g_player[myconnectindex].movefifoend&(g_movesPerPacket-1)) { - memcpy(&inputfifo[(g_player[myconnectindex].movefifoend-1)&(MOVEFIFOSIZ-1)][myconnectindex], + copybufbyte(&inputfifo[(g_player[myconnectindex].movefifoend-1)&(MOVEFIFOSIZ-1)][myconnectindex], &inputfifo[g_player[myconnectindex].movefifoend&(MOVEFIFOSIZ-1)][myconnectindex],sizeof(input_t)); g_player[myconnectindex].movefifoend++; return; @@ -2180,7 +2180,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) continue; } - memcpy(&osyn[i],&nsyn[i],sizeof(input_t)); + copybufbyte(&osyn[i],&nsyn[i],sizeof(input_t)); if (l&1) nsyn[i].fvel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2; if (l&2) nsyn[i].svel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2; if (l&4) @@ -2219,7 +2219,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) if (i != myconnectindex) for (j=g_movesPerPacket-1;j>=1;j--) { - memcpy(&nsyn[i],&inputfifo[g_player[i].movefifoend&(MOVEFIFOSIZ-1)][i],sizeof(input_t)); + copybufbyte(&nsyn[i],&inputfifo[g_player[i].movefifoend&(MOVEFIFOSIZ-1)][i],sizeof(input_t)); g_player[i].movefifoend++; } @@ -2233,7 +2233,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) osyn = (input_t *)&inputfifo[(g_player[other].movefifoend-1)&(MOVEFIFOSIZ-1)][0]; nsyn = (input_t *)&inputfifo[(g_player[other].movefifoend)&(MOVEFIFOSIZ-1)][0]; - memcpy(&osyn[other],&nsyn[other],sizeof(input_t)); + copybufbyte(&osyn[other],&nsyn[other],sizeof(input_t)); if (k&1) nsyn[other].fvel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2; if (k&2) nsyn[other].svel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2; if (k&4) @@ -2272,7 +2272,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) for (i=g_movesPerPacket-1;i>=1;i--) { - memcpy(&nsyn[other],&inputfifo[g_player[other].movefifoend&(MOVEFIFOSIZ-1)][other],sizeof(input_t)); + copybufbyte(&nsyn[other],&inputfifo[g_player[other].movefifoend&(MOVEFIFOSIZ-1)][other],sizeof(input_t)); g_player[other].movefifoend++; } @@ -2296,7 +2296,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) osyn = (input_t *)&inputfifo[(g_player[other].movefifoend-1)&(MOVEFIFOSIZ-1)][0]; nsyn = (input_t *)&inputfifo[(g_player[other].movefifoend)&(MOVEFIFOSIZ-1)][0]; - memcpy(&osyn[other],&nsyn[other],sizeof(input_t)); + copybufbyte(&osyn[other],&nsyn[other],sizeof(input_t)); k = packbuf[j] + (int)(packbuf[j+1]<<8); j += 2; @@ -2332,7 +2332,7 @@ void Net_ParsePacket(uint8_t *packbuf, int packbufleng) for (i=g_movesPerPacket-1;i>=1;i--) { - memcpy(&nsyn[other],&inputfifo[g_player[other].movefifoend&(MOVEFIFOSIZ-1)][other],sizeof(input_t)); + copybufbyte(&nsyn[other],&inputfifo[g_player[other].movefifoend&(MOVEFIFOSIZ-1)][other],sizeof(input_t)); g_player[other].movefifoend++; } @@ -2531,10 +2531,6 @@ void Net_ReceiveDisconnect(ENetEvent *event) void Net_GetPackets(void) { - MUSIC_Update(); - - G_HandleSpecialKeys(); - if (g_netDisconnect) { Net_Disconnect(); diff --git a/source/rr/src/osdcmds.cpp b/source/rr/src/osdcmds.cpp index 57b59fec9..66eecd058 100644 --- a/source/rr/src/osdcmds.cpp +++ b/source/rr/src/osdcmds.cpp @@ -169,19 +169,6 @@ static int osdcmd_noclip(osdcmdptr_t UNUSED(parm)) return OSDCMD_OK; } -static int osdcmd_restartsound(osdcmdptr_t UNUSED(parm)) -{ - UNREFERENCED_CONST_PARAMETER(parm); - S_SoundShutdown(); - - S_SoundStartup(); - - FX_StopAllSounds(); - S_ClearSoundLocks(); - - return OSDCMD_OK; -} - int osdcmd_restartmap(osdcmdptr_t UNUSED(parm)) { UNREFERENCED_CONST_PARAMETER(parm); @@ -669,7 +656,6 @@ int32_t registerosdcommands(void) OSD_RegisterFunction("printtimes", "printtimes: prints VM timing statistics", osdcmd_printtimes); OSD_RegisterFunction("restartmap", "restartmap: restarts the current map", osdcmd_restartmap); - OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound); OSD_RegisterFunction("spawn","spawn [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",osdcmd_spawn); diff --git a/source/rr/src/player.cpp b/source/rr/src/player.cpp index 434182de6..d8fb37069 100644 --- a/source/rr/src/player.cpp +++ b/source/rr/src/player.cpp @@ -4417,12 +4417,7 @@ void P_FragPlayer(int playerNum) if (!RR) S_StopEnvSound(DUKE_JETPACK_IDLE, pPlayer->i); - if (pPlayer->scream_voice > FX_Ok) - { - FX_StopSound(pPlayer->scream_voice); - S_Cleanup(); - pPlayer->scream_voice = -1; - } + S_StopEnvSound(-1, pPlayer->i, CHAN_VOICE); if (pSprite->pal != 1 && (pSprite->cstat & 32768) == 0) pSprite->cstat = 0; @@ -7123,11 +7118,9 @@ check_enemy_sprite: if (pPlayer->vel.z > 2400 && pPlayer->falling_counter < 255) { pPlayer->falling_counter++; - if (pPlayer->falling_counter >= 38 && pPlayer->scream_voice <= FX_Ok) + if (pPlayer->falling_counter >= 38 && !A_CheckSoundPlaying(pPlayer->i, -1, CHAN_VOICE)) { - int32_t voice = A_PlaySound(DUKE_SCREAM,pPlayer->i); - if (voice <= 127) // XXX: p->scream_voice is an int8_t - pPlayer->scream_voice = voice; + A_PlaySound(DUKE_SCREAM, pPlayer->i, CHAN_VOICE); } } @@ -7179,12 +7172,7 @@ check_enemy_sprite: { pPlayer->falling_counter = 0; - if (pPlayer->scream_voice > FX_Ok) - { - FX_StopSound(pPlayer->scream_voice); - S_Cleanup(); - pPlayer->scream_voice = -1; - } + S_StopEnvSound(-1, pPlayer->i, CHAN_VOICE); if ((sectorLotag != ST_1_ABOVE_WATER && sectorLotag != ST_2_UNDERWATER) && (pPlayer->on_ground == 0 && pPlayer->vel.z > (6144 >> 1))) diff --git a/source/rr/src/premap.cpp b/source/rr/src/premap.cpp index 3a98f6808..bbaea8ba2 100644 --- a/source/rr/src/premap.cpp +++ b/source/rr/src/premap.cpp @@ -575,7 +575,7 @@ void G_CacheMapData(void) starttime = timerGetTicks(); - S_PrecacheSounds(); + cacheAllSounds(); G_PrecacheSprites(); for (i=0; i= 0 && SoundEnabled()) - { - while (FX_SoundActive(g_skillSoundVoice)) - G_HandleAsync(); - } - g_skillSoundVoice = -1; ready2send = 0; @@ -2282,7 +2274,7 @@ void G_SetupFilenameBasedMusic(char *nameBuf, const char *fileName) } } - userMapRecord.music = "dethtoll.mid"; + if (!RR) userMapRecord.music = "dethtoll.mid"; } int G_EnterLevel(int gameMode) @@ -2425,7 +2417,11 @@ int G_EnterLevel(int gameMode) if (ud.recstat != 2) { - S_PlayLevelMusicOrNothing(mii); + if (Menu_HaveUserMap()) + { + S_PlayLevelMusicOrNothing(USERMAPMUSICFAKESLOT); + } + else S_PlayLevelMusicOrNothing(mii); } if (RR && !(gameMode & MODE_DEMO)) diff --git a/source/rr/src/savegame.cpp b/source/rr/src/savegame.cpp index 4059ca312..60c7e8990 100644 --- a/source/rr/src/savegame.cpp +++ b/source/rr/src/savegame.cpp @@ -35,8 +35,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_RR_NS -static OutputFileCounter savecounter; - // For storing pointers in files. // back_p==0: ptr -> "small int" // back_p==1: "small int" -> ptr diff --git a/source/rr/src/screens.cpp b/source/rr/src/screens.cpp index 462ac5da2..29ddccd1a 100644 --- a/source/rr/src/screens.cpp +++ b/source/rr/src/screens.cpp @@ -2074,7 +2074,6 @@ void G_BonusScreen(int32_t bonusonly) while (totalclock < TICRATE*10) { G_HandleAsync(); - MUSIC_Update(); if (G_FPSLimit()) { @@ -2139,7 +2138,6 @@ void G_BonusScreen(int32_t bonusonly) int32_t yy = 0, zz; G_HandleAsync(); - MUSIC_Update(); if (G_FPSLimit()) { @@ -2619,7 +2617,7 @@ void G_BonusScreenRRRA(int32_t bonusonly) if ((ud.eog == 0 || ud.volume_number != 1) && ud.volume_number <= 1) { showMap = 1; - MUSIC_StopSong(); + Mus_Stop(); inputState.keyFlushChars(); P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1); @@ -2658,7 +2656,6 @@ void G_BonusScreenRRRA(int32_t bonusonly) while (totalclock < TICRATE*10) { G_HandleAsync(); - MUSIC_Update(); if (G_FPSLimit()) { @@ -2709,7 +2706,6 @@ void G_BonusScreenRRRA(int32_t bonusonly) int32_t yy = 0, zz; G_HandleAsync(); - MUSIC_Update(); if (G_FPSLimit()) { @@ -2726,7 +2722,7 @@ void G_BonusScreenRRRA(int32_t bonusonly) if (bonuscnt == 7) { bonuscnt++; - MUSIC_StopSong(); + Mus_Stop(); G_PlayMapAnim(); break; } @@ -2979,7 +2975,7 @@ void G_BonusScreenRRRA(int32_t bonusonly) Net_GetPackets(); break; } - S_Cleanup(); + if (!S_CheckSoundPlaying(-1,35)) break; if (I_CheckAllInput()) { diff --git a/source/rr/src/sector.cpp b/source/rr/src/sector.cpp index a75f5f9e6..6f5fe66e2 100644 --- a/source/rr/src/sector.cpp +++ b/source/rr/src/sector.cpp @@ -75,9 +75,10 @@ int A_CallSound(int sectNum, int spriteNum) if (spriteNum == -1) spriteNum = SFXsprite; + auto flags = S_GetUserFlags(soundNum); if (T1(SFXsprite) == 0) { - if ((g_sounds[soundNum].m & SF_GLOBAL) == 0) + if ((flags & (SF_GLOBAL | SF_DTAG)) != SF_GLOBAL) { if (soundNum) { @@ -98,7 +99,7 @@ int A_CallSound(int sectNum, int spriteNum) if (SHT(SFXsprite)) A_PlaySound(SHT(SFXsprite), spriteNum); - if ((g_sounds[soundNum].m & SF_LOOP) || (SHT(SFXsprite) && SHT(SFXsprite) != soundNum)) + if ((flags & SF_LOOP) || (SHT(SFXsprite) && SHT(SFXsprite) != soundNum)) S_StopEnvSound(soundNum, T6(SFXsprite)); T6(SFXsprite) = spriteNum; @@ -1783,7 +1784,9 @@ default_case: S_PlaySound3D(SWITCH_ON, (switchType == SWITCH_SPRITE) ? wallOrSprite : g_player[playerNum].ps->i, &davector); else if (hitag) { - if (switchType == SWITCH_SPRITE && (g_sounds[hitag].m & SF_TALK) == 0) + auto flags = S_GetUserFlags(hitag); + + if (switchType == SWITCH_SPRITE && (flags & SF_TALK) == 0) S_PlaySound3D(hitag, wallOrSprite, &davector); else A_PlaySound(hitag, g_player[playerNum].ps->i); @@ -3037,7 +3040,7 @@ void A_DamageObject(int spriteNum, int const dmgSrc) sprite[dmgSrc].xvel = (sprite[spriteNum].xvel>>1)+(sprite[spriteNum].xvel>>2); sprite[dmgSrc].ang -= (SA(spriteNum)<<1)+1024; SA(spriteNum) = getangle(SX(spriteNum)-sprite[dmgSrc].x,SY(spriteNum)-sprite[dmgSrc].y)-512; - if (g_sounds[POOLBALLHIT].num < 2) + if (S_CheckSoundPlaying(POOLBALLHIT) < 2) A_PlaySound(POOLBALLHIT, spriteNum); } else if (RR && (sprite[dmgSrc].picnum == RRTILE3440 || sprite[dmgSrc].picnum == RRTILE3440+1)) @@ -3495,9 +3498,12 @@ default_case: SA(spriteNum) = (sprite[dmgSrc].ang + 1024) & 2047; sprite[spriteNum].xvel = -(sprite[dmgSrc].extra << 2); int16_t sectNum = SECT(spriteNum); - pushmove((vec3_t *)&sprite[spriteNum], §Num, 128L, (4L << 8), (4L << 8), CLIPMASK0); - if (sectNum != SECT(spriteNum) && (unsigned)sectNum < MAXSECTORS) - changespritesect(spriteNum, sectNum); + if ((unsigned)sectNum < MAXSECTORS) + { + pushmove((vec3_t *)&sprite[spriteNum], §Num, 128L, (4L << 8), (4L << 8), CLIPMASK0); + if (sectNum != SECT(spriteNum) && (unsigned)sectNum < MAXSECTORS) + changespritesect(spriteNum, sectNum); + } } if (sprite[spriteNum].statnum == STAT_ZOMBIEACTOR) @@ -4189,11 +4195,7 @@ rrtripbomb_case: if (pPlayer->jetpack_on) { pPlayer->inven_icon = ICON_JETPACK; - if (pPlayer->scream_voice > FX_Ok) - { - FX_StopSound(pPlayer->scream_voice); - pPlayer->scream_voice = -1; - } + S_StopEnvSound(-1, pPlayer->i, CHAN_VOICE); A_PlaySound(DUKE_JETPACK_ON,pPlayer->i); diff --git a/source/rr/src/sounds.cpp b/source/rr/src/sounds.cpp index b86632a8f..3dcba9cff 100644 --- a/source/rr/src/sounds.cpp +++ b/source/rr/src/sounds.cpp @@ -1,10 +1,9 @@ //------------------------------------------------------------------------- /* Copyright (C) 2016 EDuke32 developers and contributors +Copyright (C) 2019 Christoph Oelckers -This file is part of EDuke32. - -EDuke32 is free software; you can redistribute it and/or +This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. @@ -19,96 +18,521 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //------------------------------------------------------------------------- + #include "ns.h" // Must come before everything else! #include "compat.h" #include "duke3d.h" -#include "renderlayer.h" // for win_gethwnd() -#include "openaudio.h" #include "z_music.h" -#include #include "mapinfo.h" +#include "sound/s_soundinternal.h" BEGIN_RR_NS -#define DQSIZE 128 - -int32_t g_numEnvSoundsPlaying, g_highestSoundIdx = 0; - -static int32_t MusicIsWaveform = 0; -static char *MusicPtr = NULL; -static int32_t MusicVoice = -1; -static bool MusicPaused = false; -static bool SoundPaused = false; - -std::atomic dnum; -uint32_t dq[DQSIZE]; - -void S_SoundStartup(void) +class DukeSoundEngine : public SoundEngine { -#ifdef MIXERTYPEWIN - void *initdata = (void *) win_gethwnd(); // used for DirectSound -#else - void *initdata = NULL; -#endif + // client specific parts of the sound engine go in this class. + void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan* chan) override; + TArray ReadSound(int lumpnum); - initprintf("Initializing sound... "); - - if (FX_Init(snd_numvoices, snd_numchannels, snd_mixrate, initdata) != FX_Ok) +public: + DukeSoundEngine() { - initprintf("failed! %s\n", FX_ErrorString(FX_Error)); - return; + S_Rolloff.RolloffType = ROLLOFF_Doom; // Seems like Duke uses the same rolloff type as Doom. + S_Rolloff.MinDistance = 144; // was originally 576 which looks like a bug and sounds like crap. + S_Rolloff.MaxDistance = 1088; } +}; - initprintf("%d voices, %d channels, 16-bit %d Hz\n", *snd_numvoices, *snd_numchannels, *snd_mixrate); - - for (int i = 0; i <= g_highestSoundIdx; ++i) - { - for (auto & voice : g_sounds[i].voices) - { - g_sounds[i].num = 0; - voice.id = 0; - voice.owner = -1; - voice.dist = UINT16_MAX; - voice.clock = 0; - } - } - - S_PrecacheSounds(); - - snd_fxvolume.Callback(); - - snd_reversestereo.Callback(); - FX_SetCallBack(S_Callback); - FX_SetPrintf(OSD_Printf); +void S_InitSound() +{ + soundEngine = new DukeSoundEngine; } -void S_SoundShutdown(void) +//========================================================================== +// +// +// +//========================================================================== + +TArray DukeSoundEngine::ReadSound(int lumpnum) { - if (FX_Shutdown() != FX_Ok) - { - Bsprintf(tempbuf, "S_SoundShutdown(): error: %s", FX_ErrorString(FX_Error)); - G_GameExit(tempbuf); - } + auto wlump = fileSystem.OpenFileReader(lumpnum); + return wlump.Read(); } +//========================================================================== +// +// +// +//========================================================================== void S_PauseSounds(bool paused) { - if (SoundPaused == paused) - return; + soundEngine->SetPaused(paused); +} - SoundPaused = paused; +//========================================================================== +// +// +// +//========================================================================== - for (int i = 0; i <= g_highestSoundIdx; ++i) +void cacheAllSounds(void) +{ + auto& sfx = soundEngine->GetSounds(); + int i = 0; + for(auto &snd : sfx) { - for (auto & voice : g_sounds[i].voices) - if (voice.id > 0) - FX_PauseVoice(voice.id, paused); + soundEngine->CacheSound(&snd); + if (((++i)&31) == 0) + G_HandleAsync(); } } +//========================================================================== +// +// +// +//========================================================================== + +static inline int S_GetPitch(int num) +{ + auto const* snd = (sound_t*)soundEngine->GetUserData(num+1); + if (!snd) return 0; + int const range = abs(snd->pitchEnd - snd->pitchStart); + + return (range == 0) ? snd->pitchStart : min(snd->pitchStart, snd->pitchEnd) + rand() % range; +} + +float S_ConvertPitch(int lpitch) +{ + return pow(2, lpitch / 1200.); // I hope I got this right that ASS uses a linear scale where 1200 is a full octave. +} + +int S_GetUserFlags(int num) +{ + auto const* snd = (sound_t*)soundEngine->GetUserData(num + 1); + if (!snd) return 0; + return snd->flags; +} + +//========================================================================== +// +// +// +//========================================================================== + +int S_DefineSound(unsigned index, const char *filename, int minpitch, int maxpitch, int priority, int type, int distance, float volume) +{ + if ((unsigned)index >= MAXSOUNDS) + return -1; + + auto& S_sfx = soundEngine->GetSounds(); + index++; + unsigned oldindex = S_sfx.Size(); + if (index >= S_sfx.Size()) + { + S_sfx.Resize(index + 1); + for (; oldindex <= index; oldindex++) + { + S_sfx[oldindex].Clear(); + } + } + auto sfx = &S_sfx[index]; + bool alreadydefined = !sfx->bTentative; + sfx->UserData.Resize(sizeof(sound_t)); + auto sndinf = (sound_t*)sfx->UserData.Data(); + sndinf->flags = type & ~SF_ONEINST_INTERNAL; + if (sndinf->flags & SF_LOOP) + sndinf->flags |= SF_ONEINST_INTERNAL; + + sfx->lumpnum = fileSystem.FindFile(filename); + sndinf->pitchStart = clamp(minpitch, INT16_MIN, INT16_MAX); + sndinf->pitchEnd = clamp(maxpitch, INT16_MIN, INT16_MAX); + sndinf->priority = priority & 255; + sndinf->volAdjust = clamp(distance, INT16_MIN, INT16_MAX); + sfx->Volume = volume; + sfx->NearLimit = 6; + sfx->bTentative = false; + sfx->name = filename; + return 0; +} + + +//========================================================================== +// +// +// +//========================================================================== + +static int S_CalcDistAndAng(int spriteNum, int soundNum, int sectNum, + const vec3_t *cam, const vec3_t *pos, int *distPtr, FVector3 *sndPos) +{ + // There's a lot of hackery going on here that could be mapped to rolloff and attenuation parameters. + // However, ultimately rolloff would also just reposition the sound source so this can remain as it is. + + int orgsndist = 0, sndang = 0, sndist = 0, explosion = 0; + auto const* snd = (sound_t*)soundEngine->GetUserData(soundNum + 1); + int userflags = snd ? snd->flags : 0; + int dist_adjust = snd ? snd->volAdjust : 0; + + if (PN(spriteNum) != APLAYER || P_Get(spriteNum) != screenpeek) + { + orgsndist = sndist = FindDistance3D(cam->x - pos->x, cam->y - pos->y, (cam->z - pos->z)); + + if ((userflags & (SF_GLOBAL | SF_DTAG)) != SF_GLOBAL && S_IsAmbientSFX(spriteNum) && (sector[SECT(spriteNum)].lotag & 0xff) < 9) // ST_9_SLIDING_ST_DOOR + sndist = divscale14(sndist, SHT(spriteNum) + 1); + } + + sndist += dist_adjust; + if (sndist < 0) + sndist = 0; + + if (sectNum > -1 && sndist && PN(spriteNum) != MUSICANDSFX + && !cansee(cam->x, cam->y, cam->z - (24 << 8), sectNum, SX(spriteNum), SY(spriteNum), SZ(spriteNum) - (24 << 8), SECT(spriteNum))) + sndist += sndist>>(RR?2:5); + + // Here the sound distance was clamped to a minimum of 144*4. + // It's better to handle rolloff in the backend instead of whacking the sound origin here. + // That way the lower end can be made customizable instead of losing all precision right here at the source. + if (sndist < 0) sndist = 0; + + if (distPtr) + { + *distPtr = sndist; + } + + if (sndPos) + { + FVector3 sndorg = GetSoundPos(pos); + FVector3 campos = GetSoundPos(cam); + // Now calculate the virtual position in sound system coordinates. + FVector3 sndvec = sndorg - campos; + if (orgsndist > 0) + { + float scale = float(sndist) / orgsndist; // adjust by what was calculated above; + *sndPos = campos + sndvec * scale; + } + else *sndPos = campos; + } + + return false; +} + +//========================================================================== +// +// +// +//========================================================================== + +void S_GetCamera(vec3_t** c, int32_t* ca, int32_t* cs) +{ + if (ud.camerasprite == -1) + { + if (ud.overhead_on != 2) + { + if (c) *c = &CAMERA(pos); + if (cs) *cs = CAMERA(sect); + if (ca) *ca = fix16_to_int(CAMERA(q16ang)); + } + else + { + auto pPlayer = g_player[screenpeek].ps; + if (c) *c = &pPlayer->pos; + if (cs) *cs = pPlayer->cursectnum; + if (ca) *ca = fix16_to_int(pPlayer->q16ang); + } + } + else + { + if (c) *c = &sprite[ud.camerasprite].pos; + if (cs) *cs = sprite[ud.camerasprite].sectnum; + if (ca) *ca = sprite[ud.camerasprite].ang; + } +} + +//========================================================================= +// +// CalcPosVel +// +// The game specific part of the sound updater. +// +//========================================================================= + +void DukeSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan* chan) +{ + if (pos != nullptr) + { + vec3_t* campos; + int32_t camsect; + + S_GetCamera(&campos, nullptr, &camsect); + if (vel) vel->Zero(); + + if (type == SOURCE_Unattached) + { + pos->X = pt[0]; + pos->Y = pt[1]; + pos->Z = pt[2]; + } + else if (type == SOURCE_Actor) + { + auto actor = (spritetype*)source; + assert(actor != nullptr); + if (actor != nullptr) + { + S_CalcDistAndAng(int(actor - sprite), chanSound - 1, camsect, campos, &actor->pos, nullptr, pos); + /* + if (vel) // DN3D does not properly maintain this. + { + vel->X = float(actor->Vel.X * TICRATE); + vel->Y = float(actor->Vel.Z * TICRATE); + vel->Z = float(actor->Vel.Y * TICRATE); + } + */ + } + } + if ((chanflags & CHANF_LISTENERZ) && campos != nullptr && type != SOURCE_None) + { + pos->Y = campos->z / 256.f; + } + } +} + + +//========================================================================== +// +// +// +//========================================================================== + +void S_Update(void) +{ + SoundListener listener; + vec3_t* c; + int32_t ca, cs; + +#if 0 + if (RR /*&& todo: fix the conditions here */ ) + S_PlayRRMusic(); +#endif + + S_GetCamera(&c, &ca, &cs); + + if (c != nullptr) + { + listener.angle = -(float)ca * pi::pi() / 1024; // Build uses a period of 2048. + listener.velocity.Zero(); + listener.position = GetSoundPos(c); + listener.underwater = false; + // This should probably use a real environment instead of the pitch hacking in S_PlaySound3D. + // listenactor->waterlevel == 3; + //assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber); + listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment; + listener.valid = true; + } + else + { + listener.angle = 0; + listener.position.Zero(); + listener.velocity.Zero(); + listener.underwater = false; + listener.Environment = nullptr; + listener.valid = false; + } + listener.ListenerObject = ud.camerasprite == -1 ? nullptr : &sprite[ud.camerasprite]; + soundEngine->SetListener(listener); + soundEngine->UpdateSounds((int)totalclock); +} + + +//========================================================================== +// +// +// +//========================================================================== + +int S_PlaySound3D(int sndnum, int spriteNum, const vec3_t* pos, int channel, EChanFlags flags) +{ + auto const pPlayer = g_player[myconnectindex].ps; + if (!soundEngine->isValidSoundId(sndnum+1) || !SoundEnabled() || (unsigned)spriteNum >= MAXSPRITES || (pPlayer->gm & MODE_MENU) || + (pPlayer->timebeforeexit > 0 && pPlayer->timebeforeexit <= GAMETICSPERSEC * 3)) return -1; + + int userflags = S_GetUserFlags(sndnum); + if ((!(snd_speech & 1) && (userflags & SF_TALK)) || ((userflags & SF_ADULT) && adult_lockout)) + return -1; + + // Duke talk + if (userflags & SF_TALK) + { + if ((g_netServer || ud.multimode > 1) && PN(spriteNum) == APLAYER && P_Get(spriteNum) != screenpeek) // other player sound + { + if ((snd_speech & 4) != 4) + return -1; + } + else if ((snd_speech & 1) != 1) + return -1; + + + bool foundone = soundEngine->EnumerateChannels([&](FSoundChan* chan) + { + auto sid = chan->OrgID; + auto flags = S_GetUserFlags(sid - 1); + return !!(flags & SF_TALK); + }); + // don't play if any Duke talk sounds are already playing + if (foundone) return -1; + } + else if ((userflags & (SF_DTAG | SF_GLOBAL)) == SF_DTAG) // Duke-Tag sound + { + return S_PlaySound(sndnum); + + } + + int32_t sndist; + FVector3 sndpos; // this is in sound engine space. + + vec3_t* campos; + int32_t camsect; + + S_GetCamera(&campos, nullptr, &camsect); + S_CalcDistAndAng(spriteNum, sndnum, camsect, campos, pos, &sndist, &sndpos); + int pitch = S_GetPitch(sndnum); + auto const pOther = g_player[screenpeek].ps; + + + if (pOther->sound_pitch) + pitch += pOther->sound_pitch; + + bool explosionp = ((userflags & (SF_GLOBAL | SF_DTAG)) == (SF_GLOBAL | SF_DTAG)) || ((sndnum == PIPEBOMB_EXPLODE || sndnum == LASERTRIP_EXPLODE || sndnum == RPG_EXPLODE)); + + if (explosionp) + { + if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER) + pitch -= 1024; + } + else + { + if (sndist > 32767 && PN(spriteNum) != MUSICANDSFX && (userflags & (SF_LOOP | SF_MSFX)) == 0) + return -1; + + if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER + && (userflags & SF_TALK) == 0) + pitch = -768; + } + + bool is_playing = soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, sndnum+1); + if (is_playing && PN(spriteNum) != MUSICANDSFX) + S_StopEnvSound(sndnum, spriteNum); + + int const repeatp = (userflags & SF_LOOP); + + if (repeatp && (userflags & SF_ONEINST_INTERNAL) && is_playing) + { + return -1; + } + + // These explosion sounds originally used some distance hackery to make them louder but due to how the rolloff was set up they always played at full volume as a result. + // I think it is better to lower their attenuation so that they are louder than the rest but still fade in the distance. + // For the original effect, attenuation needs to be set to ATTN_NONE here. + float attenuation; + if (explosionp) attenuation = 0.5f; + else attenuation = (userflags & (SF_GLOBAL | SF_DTAG)) == SF_GLOBAL ? ATTN_NONE : ATTN_NORM; + + if (userflags & SF_LOOP) flags |= CHANF_LOOP; + auto chan = soundEngine->StartSound(SOURCE_Actor, &sprite[spriteNum], &sndpos, CHAN_AUTO, flags, sndnum+1, attenuation == ATTN_NONE? 0.8f : 1.f, attenuation, nullptr, S_ConvertPitch(pitch)); + return chan ? 0 : -1; +} + +//========================================================================== +// +// +// +//========================================================================== + +int S_PlaySound(int sndnum, int channel, EChanFlags flags) +{ + if (!soundEngine->isValidSoundId(sndnum+1) || !SoundEnabled()) return -1; + + int userflags = S_GetUserFlags(sndnum); + if ((!(snd_speech & 1) && (userflags & SF_TALK)) || ((userflags & SF_ADULT) && adult_lockout)) + return -1; + + int const pitch = S_GetPitch(sndnum); + + if (userflags & SF_LOOP) flags |= CHANF_LOOP; + auto chan = soundEngine->StartSound(SOURCE_None, nullptr, nullptr, channel, flags, sndnum + 1, 0.8f, ATTN_NONE, nullptr, S_ConvertPitch(pitch)); + return chan ? 0 : -1; +} + +//========================================================================== +// +// +// +//========================================================================== + +int A_PlaySound(int soundNum, int spriteNum, int channel, EChanFlags flags) +{ + return (unsigned)spriteNum >= MAXSPRITES ? S_PlaySound(soundNum, flags) : + S_PlaySound3D(soundNum, spriteNum, &sprite[spriteNum].pos, flags); +} + +void S_StopEnvSound(int sndNum, int sprNum, int flags) +{ + if (sprNum < -1 || sprNum >= MAXSPRITES) return; + + if (sprNum == -1) soundEngine->StopSoundID(sndNum+1); + else if (flags == -1) soundEngine->StopSound(SOURCE_Actor, &sprite[sprNum], -1, sndNum+1); + else soundEngine->StopSound(SOURCE_Actor, &sprite[sprNum], flags, -1); +} + +void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset) +{ + if (spriteNum < -1 || spriteNum >= MAXSPRITES) return; + double expitch = pow(2, pitchoffset / 1200.); // I hope I got this right that ASS uses a linear scale where 1200 is a full octave. + if (spriteNum == -1) + { + soundEngine->ChangeSoundPitch(SOURCE_Unattached, nullptr, CHAN_AUTO, expitch, soundNum+1); + } + else + { + soundEngine->ChangeSoundPitch(SOURCE_Actor, &sprite[spriteNum], CHAN_AUTO, expitch, soundNum+1); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +int A_CheckSoundPlaying(int spriteNum, int soundNum, int channel) +{ + if (spriteNum == -1) return soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, soundNum+1); + if ((unsigned)spriteNum >= MAXSPRITES) return false; + return soundEngine->IsSourcePlayingSomething(SOURCE_Actor, &sprite[spriteNum], channel, soundNum+1); +} + +// Check if actor is playing any sound. +int A_CheckAnySoundPlaying(int spriteNum) +{ + if ((unsigned)spriteNum >= MAXSPRITES) return false; + return soundEngine->IsSourcePlayingSomething(SOURCE_Actor, &sprite[spriteNum], CHAN_AUTO, 0); +} + +int S_CheckSoundPlaying(int soundNum) +{ + return soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, soundNum+1); +} + +//========================================================================== +// +// +// +//========================================================================== + void S_MenuSound(void) { static int SoundNum; @@ -122,21 +546,33 @@ void S_MenuSound(void) S_PlaySound(s); } +//========================================================================== +// +// Music +// +//========================================================================== + +static void S_SetMusicIndex(unsigned int m) +{ + ud.music_episode = m / MAXLEVELS; + ud.music_level = m % MAXLEVELS; +} void S_PlayLevelMusicOrNothing(unsigned int m) { - Mus_Play(mapList[m].labelName, RR ? nullptr : mapList[m].music, true); + auto& mr = m == USERMAPMUSICFAKESLOT ? userMapRecord : mapList[m]; + Mus_Play(mr.labelName, mr.music, true); + S_SetMusicIndex(m); } int S_TryPlaySpecialMusic(unsigned int m) { - if (RR) - return 1; - auto &musicfn = mapList[m].music; + auto& musicfn = mapList[m].music; if (musicfn.IsNotEmpty()) { - if (!Mus_Play(nullptr, musicfn, 1)) + if (!Mus_Play(nullptr, musicfn, true)) { + S_SetMusicIndex(m); return 0; } } @@ -144,13 +580,21 @@ int S_TryPlaySpecialMusic(unsigned int m) return 1; } +void S_PlaySpecialMusicOrNothing(unsigned int m) +{ + if (S_TryPlaySpecialMusic(m)) + { + S_SetMusicIndex(m); + } +} + void S_PlayRRMusic(int newTrack) { char fileName[16]; if (!RR || !mus_redbook) return; Mus_Stop(); - g_cdTrack = newTrack != -1 ? newTrack : g_cdTrack+1; + g_cdTrack = newTrack != -1 ? newTrack : g_cdTrack + 1; if (newTrack != 10 && (g_cdTrack > 9 || g_cdTrack < 2)) g_cdTrack = 2; @@ -158,576 +602,5 @@ void S_PlayRRMusic(int newTrack) Mus_Play(fileName, 0, true); } -void S_PlaySpecialMusicOrNothing(unsigned int m) -{ - S_TryPlaySpecialMusic(m); -} -void S_Cleanup(void) -{ - static uint32_t ldnum; - uint32_t const odnum = dnum; - - while (ldnum < odnum) - { - uint32_t num = dq[ldnum++ & (DQSIZE - 1)]; - - // negative index is RTS playback - if ((int32_t)num < 0) - { - continue; - } - - // num + (MAXSOUNDS*MAXSOUNDINSTANCES) is a sound played globally - // for which there was no open slot to keep track of the voice - if (num >= (MAXSOUNDS*MAXSOUNDINSTANCES)) - { - continue; - } - - int const vidx = num & (MAXSOUNDINSTANCES - 1); - - num = (num - vidx) / MAXSOUNDINSTANCES; - - auto &snd = g_sounds[num]; - auto &voice = g_sounds[num].voices[vidx]; - - int const spriteNum = voice.owner; - - if (EDUKE32_PREDICT_FALSE(snd.num > MAXSOUNDINSTANCES)) - OSD_Printf(OSD_ERROR "S_Cleanup(): num exceeds MAXSOUNDINSTANCES! g_sounds[%d].num %d wtf?\n", num, snd.num); - - if (snd.num > 0) - --snd.num; - - // MUSICANDSFX uses t_data[0] to control restarting the sound - // CLEAR_SOUND_T0 - if (spriteNum != -1 && S_IsAmbientSFX(spriteNum) && sector[SECT(spriteNum)].lotag < 3) // ST_2_UNDERWATER - actor[spriteNum].t_data[0] = 0; - - voice.owner = -1; - voice.id = 0; - voice.dist = UINT16_MAX; - voice.clock = 0; - } -} - -// returns number of bytes read -int32_t S_LoadSound(int num) -{ - if ((unsigned)num > (unsigned)g_highestSoundIdx || EDUKE32_PREDICT_FALSE(g_sounds[num].filename == NULL)) - return 0; - - auto &snd = g_sounds[num]; - - auto fp = S_OpenAudio(snd.filename, 0, 0); - - if (!fp.isOpen()) - { - OSD_Printf(OSDTEXT_RED "Sound %s(#%d) not found!\n", snd.filename, num); - return 0; - } - - int32_t l = fp.GetLength(); - snd.siz = l; - cacheAllocateBlock((intptr_t *)&snd.ptr, l, nullptr); - l = fp.Read(snd.ptr, l); - - return l; -} - -void S_PrecacheSounds(void) -{ - for (int32_t i = 0, j = 0; i <= g_highestSoundIdx; ++i) - if (g_sounds[i].ptr == 0) - { - j++; - if ((j&7) == 0) - G_HandleAsync(); - - S_LoadSound(i); - } -} - -static inline int S_GetPitch(int num) -{ - auto const &snd = g_sounds[num]; - int const range = klabs(snd.pe - snd.ps); - - return (range == 0) ? snd.ps : min(snd.ps, snd.pe) + rand() % range; -} - -static int S_TakeSlot(int soundNum) -{ - S_Cleanup(); - - uint16_t dist = 0; - uint16_t clock = 0; - - int bestslot = 0; - int slot = 0; - - auto &snd = g_sounds[soundNum]; - - while (slot < MAXSOUNDINSTANCES && snd.voices[slot].id > 0) - { - auto &voice = snd.voices[slot]; - - if (voice.dist > dist || (voice.dist == dist && voice.clock > clock)) - { - clock = voice.clock; - dist = voice.dist; - - bestslot = slot; - } - - slot++; - } - - if (slot != MAXSOUNDINSTANCES) - return slot; - - if (FX_SoundActive(snd.voices[bestslot].id)) - FX_StopSound(snd.voices[bestslot].id); - - dq[dnum++ & (DQSIZE-1)] = (soundNum * MAXSOUNDINSTANCES) + bestslot; - S_Cleanup(); - - return bestslot; -} - -static int S_GetSlot(int soundNum) -{ - int slot = 0; - - while (slot < MAXSOUNDINSTANCES && g_sounds[soundNum].voices[slot].id > 0) - slot++; - - return slot == MAXSOUNDINSTANCES ? S_TakeSlot(soundNum) : slot; -} - -static inline int S_GetAngle(int ang, const vec3_t *cam, const vec3_t *pos) -{ - return (2048 + ang - getangle(cam->x - pos->x, cam->y - pos->y)) & 2047; -} - -static bool S_CalcDistAndAng(int32_t spriteNum, int32_t soundNum, int32_t sectNum, int32_t angle, - const vec3_t *cam, const vec3_t *pos, - int32_t *distPtr, int32_t *angPtr) -{ - int32_t sndang = 0, sndist = 0; - bool explosion = false; - - if (PN(spriteNum) == APLAYER && P_Get(spriteNum) == screenpeek) - goto sound_further_processing; - - sndang = S_GetAngle(angle, cam, pos); - sndist = FindDistance3D(cam->x-pos->x, cam->y-pos->y, (cam->z-pos->z)); - -#ifdef SPLITSCREEN_MOD_HACKS - if (g_fakeMultiMode==2) - { - // HACK for splitscreen mod: take the min of sound distances - // to 1st and 2nd player. - - if (PN(spriteNum) == APLAYER && P_Get(spriteNum) == 1) - { - sndist = sndang = 0; - goto sound_further_processing; - } - - { - const vec3_t *cam2 = &g_player[1].ps->pos; - int32_t sndist2 = FindDistance3D(cam2->x-pos->x, cam2->y-pos->y, (cam2->z-pos->z)); - - if (sndist2 < sndist) - { - cam = cam2; - sectNum = g_player[1].ps->cursectnum; - angle = g_player[1].ps->ang; - - sndist = sndist2; - sndang = S_GetAngle(angle, cam, pos); - } - } - } -#endif - - if ((g_sounds[soundNum].m & SF_GLOBAL) == 0 && S_IsAmbientSFX(spriteNum) && (sector[SECT(spriteNum)].lotag&0xff) < 9) // ST_9_SLIDING_ST_DOOR - sndist = divscale14(sndist, SHT(spriteNum)+1); - -sound_further_processing: - sndist += g_sounds[soundNum].vo; - if (sndist < 0) - sndist = 0; - - if (sectNum > -1 && sndist && PN(spriteNum) != MUSICANDSFX - && !cansee(cam->x, cam->y, cam->z - (24 << 8), sectNum, SX(spriteNum), SY(spriteNum), SZ(spriteNum) - (24 << 8), SECT(spriteNum))) - sndist += sndist>>(RR?2:5); - - switch (DYNAMICSOUNDMAP(soundNum)) - { - case PIPEBOMB_EXPLODE__STATIC: - case LASERTRIP_EXPLODE__STATIC: - case RPG_EXPLODE__STATIC: - explosion = true; - if (sndist > 6144) - sndist = 6144; - break; - } - - if ((g_sounds[soundNum].m & SF_GLOBAL) || sndist < ((255-LOUDESTVOLUME) << 6)) - sndist = ((255-LOUDESTVOLUME) << 6); - - *distPtr = sndist; - *angPtr = sndang; - - return explosion; -} - -int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos) -{ - int32_t j; - - if (!SoundEnabled()) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn) - return -1; - - int const sndNum = num; - sound_t & snd = g_sounds[sndNum]; - - if (EDUKE32_PREDICT_FALSE((unsigned) sndNum > (unsigned) g_highestSoundIdx || snd.filename == NULL || snd.ptr == NULL)) - { - OSD_Printf("WARNING: invalid sound #%d\n", num); - return -1; - } - - const DukePlayer_t *const pPlayer = g_player[myconnectindex].ps; - - if (((snd.m & SF_ADULT) && adult_lockout) || (unsigned)spriteNum >= MAXSPRITES || (pPlayer->gm & MODE_MENU) || !FX_VoiceAvailable(snd.pr) - || (pPlayer->timebeforeexit > 0 && pPlayer->timebeforeexit <= GAMETICSPERSEC * 3)) - return -1; - - // Duke talk - if (snd.m & SF_TALK) - { - if ((g_netServer || ud.multimode > 1) && PN(spriteNum) == APLAYER && P_Get(spriteNum) != screenpeek) // other player sound - { - if ((snd_speech & 4) != 4) - return -1; - } - else if ((snd_speech & 1) != 1) - return -1; - - // don't play if any Duke talk sounds are already playing - for (j = 0; j <= g_highestSoundIdx; ++j) - if ((g_sounds[j].m & SF_TALK) && g_sounds[j].num > 0) - return -1; - } - else if (snd.m & SF_DTAG) // Duke-Tag sound - { - int const voice = S_PlaySound(sndNum); - - if (voice <= FX_Ok) - return -1; - - j = 0; - while (j < MAXSOUNDINSTANCES && snd.voices[j].id != voice) - j++; - -#ifdef DEBUGGINGAIDS - if (EDUKE32_PREDICT_FALSE(j >= MAXSOUNDINSTANCES)) - { - OSD_Printf(OSD_ERROR "%s %d: WTF?\n", __FILE__, __LINE__); - return -1; - } -#endif - - snd.voices[j].owner = spriteNum; - - return voice; - } - - int32_t sndist, sndang; - int const explosionp = S_CalcDistAndAng(spriteNum, sndNum, CAMERA(sect), fix16_to_int(CAMERA(q16ang)), &CAMERA(pos), pos, &sndist, &sndang); - int pitch = S_GetPitch(sndNum); - auto const pOther = g_player[screenpeek].ps; - -#ifdef SPLITSCREEN_MOD_HACKS - if (g_fakeMultiMode==2) - { - // splitscreen HACK - if (g_player[1].ps->i == spriteNum) - pOther = g_player[1].ps; -} -#endif - - if (pOther->sound_pitch) - pitch += pOther->sound_pitch; - - if (explosionp) - { - if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER) - pitch -= 1024; - } - else - { - if (sndist > 32767 && PN(spriteNum) != MUSICANDSFX && (snd.m & (SF_LOOP|SF_MSFX)) == 0) - return -1; - - if (pOther->cursectnum > -1 && sector[pOther->cursectnum].lotag == ST_2_UNDERWATER - && (snd.m & SF_TALK) == 0) - pitch = -768; - } - - if (snd.num > 0 && PN(spriteNum) != MUSICANDSFX) - S_StopEnvSound(sndNum, spriteNum); - - - int const sndSlot = S_GetSlot(sndNum); - - if (sndSlot >= MAXSOUNDINSTANCES) - { - return -1; - } - - int const repeatp = (snd.m & SF_LOOP); - - if (repeatp && (snd.m & SF_ONEINST_INTERNAL) && snd.num > 0) - { - return -1; - } - - // XXX: why is 'right' 0? - // Ambient MUSICANDSFX always start playing using the 3D routines! - int const ambsfxp = S_IsAmbientSFX(spriteNum); - int const voice = (repeatp && !ambsfxp) ? FX_Play(snd.ptr, snd.siz, 0, -1, pitch, sndist >> 6, sndist >> 6, 0, snd.pr, - snd.volume, (sndNum * MAXSOUNDINSTANCES) + sndSlot) - : FX_Play3D(snd.ptr, snd.siz, repeatp ? FX_LOOP : FX_ONESHOT, pitch, sndang >> 4, sndist >> 6, - snd.pr, snd.volume, (sndNum * MAXSOUNDINSTANCES) + sndSlot); - - if (voice <= FX_Ok) - { - return -1; - } - - snd.num++; - snd.voices[sndSlot].owner = spriteNum; - snd.voices[sndSlot].id = voice; - snd.voices[sndSlot].dist = sndist >> 6; - snd.voices[sndSlot].clock = 0; - - return voice; -} - -int S_PlaySound(int num) -{ - int sndnum; - - if (!SoundEnabled()) // check that the user returned -1, but only if -1 wasn't playing already (in which case, warn) - return -1; - - sound_t & snd = g_sounds[num]; - - if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_highestSoundIdx || snd.filename == NULL || snd.ptr == NULL)) - { - OSD_Printf("WARNING: invalid sound #%d\n",num); - return -1; - } - - if ((!(snd_speech & 1) && (snd.m & SF_TALK)) || ((snd.m & SF_ADULT) && adult_lockout) || !FX_VoiceAvailable(snd.pr)) - return -1; - - int const pitch = S_GetPitch(num); - - sndnum = S_GetSlot(num); - - if (sndnum >= MAXSOUNDINSTANCES) - { - return -1; - } - - int const voice = (snd.m & SF_LOOP) ? FX_Play(snd.ptr, snd.siz, 0, -1, pitch, LOUDESTVOLUME, LOUDESTVOLUME, - LOUDESTVOLUME, snd.siz, snd.volume, (num * MAXSOUNDINSTANCES) + sndnum) - : FX_Play3D(snd.ptr, snd.siz, FX_ONESHOT, pitch, 0, 255 - LOUDESTVOLUME, snd.pr, snd.volume, - (num * MAXSOUNDINSTANCES) + sndnum); - - if (voice <= FX_Ok) - { - return -1; - } - - snd.num++; - snd.voices[sndnum].owner = -1; - snd.voices[sndnum].id = voice; - snd.voices[sndnum].dist = 255 - LOUDESTVOLUME; - snd.voices[sndnum].clock = 0; - - return voice; -} - -int A_PlaySound(int soundNum, int spriteNum) -{ - if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return -1; - - return (unsigned)spriteNum >= MAXSPRITES ? S_PlaySound(soundNum) : - S_PlaySound3D(soundNum, spriteNum, (vec3_t *)&sprite[spriteNum]); -} - -void S_StopEnvSound(int32_t num, int32_t i) -{ - if (EDUKE32_PREDICT_FALSE((unsigned)num > (unsigned)g_highestSoundIdx) || g_sounds[num].num <= 0) - return; - - int32_t j; - - do - { - for (j=0; j FX_Ok) || (i != -1 && g_sounds[num].voices[j].owner == i)) - { -#ifdef DEBUGGINGAIDS - if (EDUKE32_PREDICT_FALSE(i >= 0 && g_sounds[num].voices[j].id <= FX_Ok)) - initprintf(OSD_ERROR "S_StopEnvSound(): bad voice %d for sound ID %d index %d!\n", g_sounds[num].voices[j].id, num, j); - else -#endif - if (g_sounds[num].voices[j].id > FX_Ok) - { - FX_StopSound(g_sounds[num].voices[j].id); - S_Cleanup(); - break; - } - } - } - } - while (j < MAXSOUNDINSTANCES); -} - -// Do not remove this or make it inline. -void S_StopAllSounds(void) -{ - FX_StopAllSounds(); -} - -void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset) -{ - if ((unsigned)soundNum > (unsigned)g_highestSoundIdx || g_sounds[soundNum].num <= 0) - return; - - for (auto &voice : g_sounds[soundNum].voices) - { - if ((spriteNum == -1 && voice.id > FX_Ok) || (spriteNum != -1 && voice.owner == spriteNum)) - { - if (EDUKE32_PREDICT_FALSE(spriteNum >= 0 && voice.id <= FX_Ok)) - initprintf(OSD_ERROR "S_ChangeSoundPitch(): bad voice %d for sound ID %d!\n", voice.id, soundNum); - else if (voice.id > FX_Ok && FX_SoundActive(voice.id)) - FX_SetPitch(voice.id, pitchoffset); - break; - } - } -} - -void S_Update(void) -{ - S_Cleanup(); - - if ((g_player[myconnectindex].ps->gm & (MODE_GAME|MODE_DEMO)) == 0) - return; - - if (RR && MusicIsWaveform && MusicVoice >= 0 && !FX_SoundActive(MusicVoice)) - S_PlayRRMusic(); - - g_numEnvSoundsPlaying = 0; - - const vec3_t *c; - int32_t ca,cs; - - if (ud.camerasprite == -1) - { - c = &CAMERA(pos); - cs = CAMERA(sect); - ca = fix16_to_int(CAMERA(q16ang)); - } - else - { - c = (vec3_t *)&sprite[ud.camerasprite]; - cs = sprite[ud.camerasprite].sectnum; - ca = sprite[ud.camerasprite].ang; - } - - int sndnum = 0; - int const highest = g_highestSoundIdx; - - do - { - if (g_sounds[sndnum].num == 0) - continue; - - for (auto &voice : g_sounds[sndnum].voices) - { - int const spriteNum = voice.owner; - - if ((unsigned)spriteNum >= MAXSPRITES || voice.id <= FX_Ok || !FX_SoundActive(voice.id)) - continue; - - int32_t sndist, sndang; - - S_CalcDistAndAng(spriteNum, sndnum, cs, ca, c, (const vec3_t *)&sprite[spriteNum], &sndist, &sndang); - - if (S_IsAmbientSFX(spriteNum)) - g_numEnvSoundsPlaying++; - - // AMBIENT_SOUND - FX_Pan3D(voice.id, sndang >> 4, sndist >> 6); - voice.dist = sndist >> 6; - voice.clock++; - } - } while (++sndnum <= highest); -} - -void S_Callback(intptr_t num) -{ - if (num == MUSIC_ID) - return; - - dq[dnum & (DQSIZE - 1)] = (uint32_t)num; - dnum++; -} - - -bool A_CheckSoundPlaying(int spriteNum, int soundNum) -{ - if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return 0; - - if (g_sounds[soundNum].num > 0 && spriteNum >= 0) - { - for (auto &voice : g_sounds[soundNum].voices) - if (voice.owner == spriteNum) - return 1; - } - - return (spriteNum == -1) ? (g_sounds[soundNum].num != 0) : 0; -} - -// Check if actor is playing any sound. -bool A_CheckAnySoundPlaying(int spriteNum) -{ - int const msp = g_highestSoundIdx; - - for (int j = 0; j <= msp; ++j) - { - for (auto &voice : g_sounds[j].voices) - if (voice.owner == spriteNum) - return 1; - } - - return 0; -} - -bool S_CheckSoundPlaying(int spriteNum, int soundNum) -{ - if (EDUKE32_PREDICT_FALSE((unsigned)soundNum > (unsigned)g_highestSoundIdx)) return false; - return (g_sounds[soundNum].num != 0); -} - -END_RR_NS +END_DUKE_NS diff --git a/source/rr/src/sounds.h b/source/rr/src/sounds.h index 39cb58900..b4ac69e41 100644 --- a/source/rr/src/sounds.h +++ b/source/rr/src/sounds.h @@ -30,61 +30,45 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define sounds_public_h_ #include "sounds_common.h" +#include "sound/s_soundinternal.h" #include "z_music.h" BEGIN_RR_NS // KEEPINSYNC lunatic/con_lang.lua #define MAXSOUNDS 4096 -#define MAXSOUNDINSTANCES 8 #define LOUDESTVOLUME 111 -#define MUSIC_ID -65536 typedef struct { - int16_t owner; - int16_t id; - uint16_t dist; - uint16_t clock; -} assvoice_t; - -typedef struct -{ - char * ptr, *filename; // 8b/16b - int32_t length, num, siz; // 12b - float volume; // 4b - assvoice_t voices[MAXSOUNDINSTANCES]; // 64b - int16_t ps, pe, vo; // 6b - char pr, m; // 2b + int pitchStart, pitchEnd, volAdjust; + int priority, flags; } sound_t; -extern sound_t g_sounds[MAXSOUNDS]; -extern int32_t g_skillSoundVoice; -extern int32_t g_numEnvSoundsPlaying,g_highestSoundIdx; - -bool A_CheckSoundPlaying(int spriteNum,int soundNum); -int A_PlaySound(int soundNum, int spriteNum); -void S_Callback(intptr_t num); -bool A_CheckAnySoundPlaying(int spriteNum); -bool S_CheckSoundPlaying(int spriteNum,int soundNum); -void S_Cleanup(void); +int A_CheckSoundPlaying(int spriteNum, int soundNum, int channel = 0); +int A_PlaySound(int soundNum, int spriteNum, int channel = CHAN_AUTO, EChanFlags flags = 0); +int A_CheckAnySoundPlaying(int spriteNum); +int S_CheckSoundPlaying(int soundNum); +inline int S_CheckSoundPlaying(int sprnum, int soundNum) { return S_CheckSoundPlaying(soundNum); } inline void S_ClearSoundLocks(void) {} -int32_t S_LoadSound(uint32_t num); -void S_PrecacheSounds(void); +void cacheAllSounds(void); void S_MenuSound(void); +void S_PauseMusic(bool paused); void S_PauseSounds(bool paused); -void S_PlayRRMusic(int newTrack = -1); void S_PlayLevelMusicOrNothing(unsigned int); int S_TryPlaySpecialMusic(unsigned int); void S_PlaySpecialMusicOrNothing(unsigned int); -int S_PlaySound(int num); -int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos); -void S_SoundShutdown(void); -void S_SoundStartup(void); -void S_StopEnvSound(int32_t num,int32_t i); +void S_ContinueLevelMusic(void); +int S_PlaySound(int num, int channel = CHAN_AUTO, EChanFlags flags = 0); +int S_PlaySound3D(int num, int spriteNum, const vec3_t *pos, int channel = CHAN_AUTO, EChanFlags flags = 0); +void S_StopEnvSound(int sndNum,int sprNum, int flags = -1); void S_StopAllSounds(void); void S_Update(void); void S_ChangeSoundPitch(int soundNum, int spriteNum, int pitchoffset); +int S_GetUserFlags(int sndnum); +int S_DefineSound(unsigned index, const char* filename, int ps, int pe, int pr, int m, int vo, float vol); +void S_InitSound(); +void S_PlayRRMusic(int newTrack = -1); static inline bool S_IsAmbientSFX(int spriteNum) { diff --git a/source/sw/CMakeLists.txt b/source/sw/CMakeLists.txt index 6de3ea9b1..d64f1b649 100644 --- a/source/sw/CMakeLists.txt +++ b/source/sw/CMakeLists.txt @@ -7,14 +7,13 @@ endif() include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/../../build/include" ) if (WIN32) - include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/vpx" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/sdl2") + include_directories( "${ZMUSIC_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/vpx" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/sdl2") else () -include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GDTOA_INCLUDE_DIR}") +include_directories( "${ZLIB_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GDTOA_INCLUDE_DIR}") endif() include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../build/include - ${CMAKE_CURRENT_SOURCE_DIR}/../mact/include ${CMAKE_CURRENT_SOURCE_DIR}/../audiolib/include ${CMAKE_CURRENT_SOURCE_DIR}/../libsmackerdec/include ${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/include @@ -25,6 +24,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../common/fonts ${CMAKE_CURRENT_SOURCE_DIR}/../common/2d ${CMAKE_CURRENT_SOURCE_DIR}/../common/music + ${CMAKE_CURRENT_SOURCE_DIR}/../common/input ${CMAKE_CURRENT_SOURCE_DIR}/../platform ) diff --git a/source/sw/src/actor.cpp b/source/sw/src/actor.cpp index 703467495..ec231b0ec 100644 --- a/source/sw/src/actor.cpp +++ b/source/sw/src/actor.cpp @@ -152,7 +152,7 @@ DoActorDie(short SpriteNum, short weapon) SpawnBlood(SpriteNum, SpriteNum, -1, -1, -1, -1); InitPlasmaFountain(wp, sp); InitPlasmaFountain(wp, sp); - PlaySound(DIGI_NINJAINHALF,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_NINJAINHALF, sp, v3df_none); if (sw_ninjahack) ChangeState(SpriteNum, &s_NinjaDieSlicedHack[5]); else @@ -830,11 +830,11 @@ DoActorStopFall(short SpriteNum) if (TEST(u->Flags, SPR_DEAD)) { NewStateGroup(SpriteNum, u->ActorActionSet->Dead); - PlaySound(DIGI_ACTORBODYFALL1,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_ACTORBODYFALL1, sp, v3df_none); } else { - PlaySound(DIGI_ACTORHITGROUND,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_ACTORHITGROUND, sp, v3df_none); NewStateGroup(SpriteNum, u->ActorActionSet->Run); diff --git a/source/sw/src/anim.cpp b/source/sw/src/anim.cpp index de3e0e216..09dc527f2 100644 --- a/source/sw/src/anim.cpp +++ b/source/sw/src/anim.cpp @@ -26,16 +26,12 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "ns.h" #include "build.h" -#include "cache1d.h" + #include "keys.h" #include "mytypes.h" -#include "fx_man.h" -#include "music.h" #include "gamedefs.h" -#include "keyboard.h" -#include "control.h" #include "config.h" #include "sounds.h" #include "gamecontrol.h" @@ -79,7 +75,7 @@ void AnimShareIntro(int frame, int numframes) ototalclock += 120; else if (frame == 1) { - PlaySound(DIGI_NOMESSWITHWANG,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_NOMESSWITHWANG, v3df_none); ototalclock += 120*3; } else @@ -87,11 +83,11 @@ void AnimShareIntro(int frame, int numframes) if (frame == 5) { - PlaySound(DIGI_INTRO_SLASH,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_INTRO_SLASH, v3df_none); } else if (frame == 15) { - PlaySound(DIGI_INTRO_WHIRL,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_INTRO_WHIRL, v3df_none); } } @@ -105,26 +101,26 @@ void AnimSerp(int frame, int numframes) if (frame == 1) { - PlaySound(DIGI_SERPTAUNTWANG,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_SERPTAUNTWANG, v3df_none); } else if (frame == 16) { - PlaySound(DIGI_SHAREND_TELEPORT,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_SHAREND_TELEPORT, v3df_none); } else if (frame == 35) { SoundState++; - PlaySound(DIGI_WANGTAUNTSERP1,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_WANGTAUNTSERP1, v3df_none); } else if (frame == 51) { SoundState++; - PlaySound(DIGI_SHAREND_UGLY1,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_SHAREND_UGLY1, v3df_none); } else if (frame == 64) { SoundState++; - PlaySound(DIGI_SHAREND_UGLY2,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_SHAREND_UGLY2, v3df_none); } } @@ -142,19 +138,19 @@ void AnimSumo(int frame, int numframes) if (frame == 2) { // hungry - PlaySound(DIGI_JG41012,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_JG41012, v3df_none); } else if (frame == 30) { - PlaySound(DIGI_HOTHEADSWITCH,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_HOTHEADSWITCH, v3df_none); } else if (frame == 42) { - PlaySound(DIGI_HOTHEADSWITCH,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_HOTHEADSWITCH, v3df_none); } else if (frame == 59) { - PlaySound(DIGI_JG41028,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_JG41028, v3df_none); } } @@ -168,103 +164,64 @@ void AnimZilla(int frame, int numframes) if (frame == 1) { - PlaySound(DIGI_ZC1,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC1, v3df_none); } else if (frame == 5) { - PlaySound(DIGI_JG94024,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_JG94024, v3df_none); } else if (frame == 14) { - PlaySound(DIGI_ZC2,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC2, v3df_none); } else if (frame == 30) { - PlaySound(DIGI_ZC3,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC3, v3df_none); } else if (frame == 32) { - PlaySound(DIGI_ZC4,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC4, v3df_none); } else if (frame == 37) { - PlaySound(DIGI_ZC5,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC5, v3df_none); } else if (frame == 63) { - PlaySound(DIGI_Z16043,&zero,&zero,&zero,v3df_none); - PlaySound(DIGI_ZC6,&zero,&zero,&zero,v3df_none); - PlaySound(DIGI_ZC7,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_Z16043, v3df_none); + PlaySound(DIGI_ZC6, v3df_none); + PlaySound(DIGI_ZC7, v3df_none); } else if (frame == 72) { - PlaySound(DIGI_ZC7,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC7, v3df_none); } else if (frame == 73) { - PlaySound(DIGI_ZC4,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC4, v3df_none); } else if (frame == 77) { - PlaySound(DIGI_ZC5,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC5, v3df_none); } else if (frame == 87) { - PlaySound(DIGI_ZC8,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC8, v3df_none); } else if (frame == 103) { - PlaySound(DIGI_ZC7,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC7, v3df_none); } else if (frame == 108) { - PlaySound(DIGI_ZC9,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_ZC9, v3df_none); } else if (frame == 120) { - PlaySound(DIGI_JG94039,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_JG94039, v3df_none); } } -unsigned char *LoadAnm(short anim_num, int *lengthp) -{ - int length; - unsigned char *animbuf, *palptr; - int i,j,k; - - DSPRINTF(ds,"LoadAnm"); - MONO_PRINT(ds); - - // this seperate allows the anim to be precached easily - - ANIMnum = anim_num; - - // lock it - - int file = fileSystem.FindFile(ANIMname[ANIMnum]); - if (file < 0) return nullptr; - *lengthp = length = fileSystem.FileLength(file); - - if (anm_ptr[anim_num] == 0) - { - auto handle = fileSystem.OpenFileReader(file); - if (!handle.isOpen()) - return NULL; - - buffer.Resize(length + sizeof(anim_t)); - anm_ptr[anim_num] = (anim_t*)buffer.Data(); - animbuf = (unsigned char *)((intptr_t)anm_ptr[anim_num] + sizeof(anim_t)); - - handle.Read(animbuf, length); - } - else - { - animbuf = (unsigned char *)((intptr_t)anm_ptr[anim_num] + sizeof(anim_t)); - } - - return animbuf; -} - void playanm(short anim_num) { @@ -283,14 +240,19 @@ playanm(short anim_num) DSPRINTF(ds,"PlayAnm"); MONO_PRINT(ds); - animbuf = LoadAnm(anim_num, &length); - if (!animbuf) - return; + TArray buffer; + auto fr = fileSystem.OpenFileReader(ANIMname[ANIMnum], 0); + + if (!fr.isOpen()) + goto ENDOFANIMLOOP; + + buffer = fr.ReadPadded(1); + fr.Close(); DSPRINTF(ds,"PlayAnm - Palette Stuff"); MONO_PRINT(ds); - ANIM_LoadAnim(animbuf, length); + ANIM_LoadAnim(buffer.Data(), buffer.Size()-1); ANIMnumframes = ANIM_NumFrames(); numframes = ANIMnumframes; @@ -319,14 +281,18 @@ playanm(short anim_num) switch (ANIMnum) { case ANIM_INTRO: - if (I_GeneralTrigger()) - I_GeneralTriggerClear(); + if (I_GeneralTrigger()) + { + I_GeneralTriggerClear(); goto ENDOFANIMLOOP; + } break; case ANIM_SERP: - if (I_EscapeTrigger()) - I_EscapeTriggerClear(); + if (I_EscapeTrigger()) + { + I_EscapeTriggerClear(); goto ENDOFANIMLOOP; + } break; } @@ -349,7 +315,7 @@ playanm(short anim_num) break; } - TileFiles.tileSetExternal(ANIM_TILE(ANIMnum), 200, 320, ANIM_DrawFrame(1)); + TileFiles.tileSetExternal(ANIM_TILE(ANIMnum), 200, 320, ANIM_DrawFrame(i)); tileInvalidate(ANIM_TILE(ANIMnum), 0, 1<<4); rotatesprite(0 << 16, 0 << 16, 65536L, 512, ANIM_TILE(ANIMnum), 0, 0, 2 + 4 + 8 + 16 + 64, 0, 0, xdim - 1, ydim - 1); diff --git a/source/sw/src/border.cpp b/source/sw/src/border.cpp index ac5609702..e6ea9db38 100644 --- a/source/sw/src/border.cpp +++ b/source/sw/src/border.cpp @@ -545,6 +545,7 @@ void SetBorder(PLAYERp pp, int value) gs.BorderNum = SIZ(BorderInfoValues) - 1; return; } + if (xdim == 0) return; // game not set up yet. BorderSetView(pp, &Xdim, &Ydim, &ScreenSize); diff --git a/source/sw/src/bunny.cpp b/source/sw/src/bunny.cpp index 7f49aa10f..f8495bcb5 100644 --- a/source/sw/src/bunny.cpp +++ b/source/sw/src/bunny.cpp @@ -997,8 +997,8 @@ DoBunnyQuickJump(short SpriteNum) { if (u->spal == PALETTE_PLAYER8 && tu->spal == PALETTE_PLAYER8) { - PlaySound(DIGI_BUNNYATTACK, &sp->x, &sp->y, &sp->z, v3df_follow); - PlaySound(DIGI_BUNNYDIE2, &tsp->x, &tsp->y, &tsp->z, v3df_follow); + PlaySound(DIGI_BUNNYATTACK, sp, v3df_follow); + PlaySound(DIGI_BUNNYDIE2, tsp, v3df_follow); tu->Health = 0; // Blood fountains @@ -1060,7 +1060,7 @@ DoBunnyQuickJump(short SpriteNum) { choose_snd = STD_RANDOM_RANGE(2<<8)>>8; if (FAFcansee(sp->x,sp->y,SPRITEp_TOS(sp),sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum) && FACING(sp, u->tgt_sp)) - PlayerSound(fagsnds[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_doppler|v3df_follow|v3df_dontpan,pp); + PlayerSound(fagsnds[choose_snd], v3df_doppler|v3df_follow|v3df_dontpan,pp); } } } @@ -1076,7 +1076,7 @@ DoBunnyQuickJump(short SpriteNum) { choose_snd = STD_RANDOM_RANGE(3<<8)>>8; if (FAFcansee(sp->x,sp->y,SPRITEp_TOS(sp),sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum) && FACING(sp, u->tgt_sp)) - PlayerSound(straightsnds[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_doppler|v3df_follow|v3df_dontpan,pp); + PlayerSound(straightsnds[choose_snd], v3df_doppler|v3df_follow|v3df_dontpan,pp); } } } @@ -1171,7 +1171,7 @@ int DoBunnyStandKill(short SpriteNum) // Growl like the bad ass bunny you are! if (RANDOM_RANGE(1000) > 800) - PlaySound(DIGI_BUNNYATTACK,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_BUNNYATTACK, sp, v3df_none); if ((u->WaitTics -= ACTORMOVETICS) <= 0) NewStateGroup(SpriteNum, sg_BunnyRun); @@ -1488,7 +1488,7 @@ DoBunnyScrew(short SpriteNum) if (RANDOM_RANGE(1000) > 990) // Bunny sex sounds { if (!adult_lockout && !Global_PLock) - PlaySound(DIGI_BUNNYATTACK, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_BUNNYATTACK, sp, v3df_follow); } u->WaitTics -= ACTORMOVETICS; @@ -1538,7 +1538,7 @@ DoBunnyGrowUp(short SpriteNum) { if (Bunny_Count < 20) { - PlaySound(DIGI_BUNNYDIE2, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_BUNNYDIE2, sp, v3df_follow); BunnyHatch(SpriteNum); // Baby time } u->ShellNum = 0; // Not pregnent anymore diff --git a/source/sw/src/cache.cpp b/source/sw/src/cache.cpp index 3ab5fc762..2186bf52b 100644 --- a/source/sw/src/cache.cpp +++ b/source/sw/src/cache.cpp @@ -407,11 +407,13 @@ void PreCacheSoundList(short table[], int num) { short j; +#if 0 for (j = 0; j < num; j++) { CacheSound(table[j], CACHE_SOUND_PRECACHE); AnimateCacheCursor(); } +#endif } void diff --git a/source/sw/src/cheats.cpp b/source/sw/src/cheats.cpp index 529d38fd1..27db405cd 100644 --- a/source/sw/src/cheats.cpp +++ b/source/sw/src/cheats.cpp @@ -43,7 +43,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "mytypes.h" #include "text.h" -#include "control.h" #include "gamecontrol.h" #include "gstrings.h" //#include "inv.h" @@ -398,12 +397,12 @@ void EveryCheatToggle(PLAYERp pp, const char *cheat_string) void GeorgeFunc(PLAYERp pp, char *) { - PlayerSound(DIGI_TAUNTAI9,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_TAUNTAI9, v3df_dontpan|v3df_doppler|v3df_follow,pp); } void BlackburnFunc(PLAYERp pp, char *) { - PlayerSound(DIGI_TAUNTAI3,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_TAUNTAI3, v3df_dontpan|v3df_doppler|v3df_follow,pp); } int cheatcmp(const char *str1, const char *str2, int len) diff --git a/source/sw/src/config.cpp b/source/sw/src/config.cpp index 9acd0cc0d..9bdb6b9ae 100644 --- a/source/sw/src/config.cpp +++ b/source/sw/src/config.cpp @@ -33,10 +33,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "settings.h" #include "mytypes.h" #include "gamedefs.h" -#include "keyboard.h" #include "gamecontrol.h" -#include "control.h" -#include "fx_man.h" #include "sounds.h" #include "config.h" #include "common_game.h" @@ -44,6 +41,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms // we load this in to get default button and key assignments // as well as setting up function mappings +#include "renderlayer.h" + #if defined RENDERTYPESDL && defined SDL_TARGET && SDL_TARGET > 1 # include "sdl_inc.h" #endif diff --git a/source/sw/src/config.h b/source/sw/src/config.h index 0a1726dac..89f91ac51 100644 --- a/source/sw/src/config.h +++ b/source/sw/src/config.h @@ -30,8 +30,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "compat.h" #include "gamecontrol.h" -#include "keyboard.h" -#include "control.h" BEGIN_SW_NS diff --git a/source/sw/src/console.cpp b/source/sw/src/console.cpp index b6afca650..ce8491786 100644 --- a/source/sw/src/console.cpp +++ b/source/sw/src/console.cpp @@ -45,7 +45,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "common_game.h" #include "gamecontrol.h" -#include "control.h" #include "trigger.h" #include "savedef.h" @@ -75,10 +74,6 @@ uint8_t CON_CommandCmp(const char *str1, const char *str2, int len); void CheatInput(void); // Modify actor routines -void CON_ModXrepeat(void); -void CON_ModYrepeat(void); -void CON_ModTranslucent(void); -void CON_GetHelp(void); void CON_Sound(void); void CON_Reverb(void); void CON_Heap(void); @@ -92,13 +87,11 @@ void CON_Quit(void); void CON_LoadSetup(void); void CON_DamageData(void); void CON_WinPachinko(void); -void CON_Tweak(void); void CON_Bunny(void); void CON_CheckHeap(void); void CON_DumpHeap(void); void CON_ShowMirror(void); void CON_MultiNameChange(void); -void CON_DumpSoundList(void); // STRUCTURES //////////////////////////////////////////////////////////////////////////////// @@ -129,24 +122,8 @@ CON_COMMAND pre_commands[] = {"george", CheatInput}, {"blackburn", CheatInput}, {"reverb", CON_Reverb}, - {"mem", CON_Heap}, - {"cache", CON_Cache}, - {"xrepeat", CON_ModXrepeat}, - {"yrepeat", CON_ModYrepeat}, - {"translucent", CON_ModTranslucent}, - {"spriteinfo", CON_SpriteInfo}, - {"kill", CON_KillSprite}, - {"showsprite", CON_SpriteDetail}, - {"showuser", CON_UserDetail}, - {"damage", CON_DamageData}, - {"tweak", CON_Tweak}, - {"checkheap", CON_CheckHeap}, - {"dumpheap", CON_DumpHeap}, {"showmirror", CON_ShowMirror}, {"clear", CON_ClearConsole}, - {"dumpsounds", CON_DumpSoundList}, - {"help", CON_GetHelp}, -//{"quit", CON_Quit}, #endif {"swgod", CheatInput}, {"swchan", CheatInput}, @@ -172,11 +149,7 @@ CON_COMMAND pre_commands[] = {"swgun#", CheatInput}, {"swquit", CheatInput}, {"swexit", CheatInput}, - {"sound", CON_SoundTest}, - {"winpachinko", CON_WinPachinko}, - {"config", CON_LoadSetup}, {"swtrix", CON_Bunny}, - {"swname", CON_MultiNameChange}, {NULL, NULL} }; @@ -397,213 +370,6 @@ void CON_ClearConsole(void) strcpy(con_quote[i],"\0"); } -///////////////////////////////////////////////////////////////////////////////////////////// -// The user console programming function library //////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////// - -SWBOOL CheckValidSprite(short SpriteNum) -{ - if (SpriteNum < 0 || SpriteNum > 6144) - { - OSD_Printf("ERROR: Sprite %d is out of range.",SpriteNum); - return FALSE; - } - return TRUE; -} - -// Get help on a console command -void CON_GetHelp(void) -{ - char base[80], command[80]; - short i; - - - if (sscanf(MessageInputString,"%s %s",base,command) < 2) - { - OSD_Printf("Usage: help [keyword]"); - return; - } - - Bstrlwr(command); // Make sure operator is all lower case - - if (!strcmp(command, "xrepeat")) - { - OSD_Printf("Usage: xrepeat [repeat value 0-255],"); - OSD_Printf(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); - return; - } - else if (!strcmp(command, "yrepeat")) - { - OSD_Printf("Usage: yrepeat [repeat value 0-255],"); - OSD_Printf(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); - return; - } - else if (!strcmp(command, "translucent")) - { - OSD_Printf("Usage: translucent [OFF/ON 0-1],"); - OSD_Printf(" [User ID (-1 for all ID's)], [SpriteNum (-1 for all of type ID)]"); - return; - } - else - { - OSD_Printf("No help was located on that subject."); - } -} - -// Modify sprites xrepeat value -void CON_ModXrepeat(void) -{ - char base[80]; - int16_t op1=64,op2=-1,op3=-1; - short i; - - - if (sscanf(MessageInputString,"%s %hd %hd %hd",base,&op1,&op2,&op3) < 4) - { - strcpy(MessageInputString,"help xrepeat"); - CON_GetHelp(); - return; - } - - if (op3 == -1) - { - for (i=0; ixrepeat = op1; - else - { - if (u->ID == op2) - sp->xrepeat = op1; - } - } - if (op2 == -1) - OSD_Printf("Xrepeat set to %d for all u->ID's for all sprites.",op1); - else - OSD_Printf("Xrepeat set to %d for u->ID = %d for all sprites.",op1,op2); - } - else - { - // Do it only for one sprite - SPRITEp sp = &sprite[op3]; - USERp u = User[op3]; - - if (!CheckValidSprite(op3)) return; - - sp->xrepeat = op1; - OSD_Printf("Xrepeat set to %d for sprite %d.",op1,op3); - } -} - -// Modify sprites yrepeat value -void CON_ModYrepeat(void) -{ - char base[80]; - int16_t op1=64,op2=-1,op3=-1; - short i; - - - if (sscanf(MessageInputString,"%s %hd %hd %hd",base,&op1,&op2,&op3) < 4) - { - strcpy(MessageInputString,"help yrepeat"); - CON_GetHelp(); - return; - } - - - if (op3 == -1) - { - for (i=0; iyrepeat = op1; - else - { - if (u->ID == op2) - sp->yrepeat = op1; - } - } - if (op2 == -1) - OSD_Printf("Yrepeat set to %d for all u->ID's for all sprites.",op1); - else - OSD_Printf("Yrepeat set to %d for u->ID = %d for all sprites.",op1,op2); - } - else - { - // Do it only for one sprite - SPRITEp sp = &sprite[op3]; - USERp u = User[op3]; - - if (!CheckValidSprite(op3)) return; - - sp->yrepeat = op1; - OSD_Printf("Yrepeat set to %d for sprite %d.",op1,op3); - } -} - -void CON_ModTranslucent(void) -{ - char base[80]; - int16_t op1=0; - SPRITEp sp; - USERp u; - - // Format: translucent [SpriteNum] - if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) - { - strcpy(MessageInputString,"help translucent"); - CON_GetHelp(); - return; - } - - if (!CheckValidSprite(op1)) return; - - sp = &sprite[op1]; - u = User[op1]; - - if (TEST(sp->cstat,CSTAT_SPRITE_TRANSLUCENT)) - { - RESET(sp->cstat,CSTAT_SPRITE_TRANSLUCENT); - OSD_Printf("Translucence RESET for sprite %d.",op1); - } - else - { - SET(sp->cstat,CSTAT_SPRITE_TRANSLUCENT); - OSD_Printf("Translucence SET for sprite %d.",op1); - } -} - -void CON_SoundTest(void) -{ - int handle; - int zero=0; - char base[80]; - int16_t op1=0; - - // Format: sound [number] - if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) - { - strcpy(MessageInputString,"help sound"); - CON_GetHelp(); - return; - } - - if (op1 < 0 || op1 >= DIGI_MAX) - { - OSD_Printf("Sound number out of range."); - return; - } - - handle = PlaySound(op1,&zero,&zero,&zero,v3df_none); -} - - void CON_Reverb(void) { char base[80]; @@ -614,7 +380,6 @@ void CON_Reverb(void) if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) { strcpy(MessageInputString,"help reverb"); - CON_GetHelp(); return; } @@ -622,641 +387,6 @@ void CON_Reverb(void) COVER_SetReverb(op1); pp->Reverb = op1; } - -void CON_Heap(void) -{ - /* - int totalmemory=0; - extern int TotalMemory, ActualHeap; - int i; - void *testheap; - - totalmemory = Z_AvailHeap(); - OSD_Printf("Total heap at game startup = %d", TotalMemory); - OSD_Printf("ActualHeap reserved for non-cache use = %d", ActualHeap); - OSD_Printf("Total unallocated blocks in bytes minus reserved heap = %d", totalmemory); - OSD_Printf("NOTE: Allocation exceeding ActualHeap will result in out of memory"); - // Find remaining heap space unused - i = ActualHeap; - while(i>0) - { - testheap = AllocMem(i); - if(!testheap) - i-=1024L; // Decrease in 1k increments - else - { - OSD_Printf("Heap test result (+ or - 1k):"); - OSD_Printf("============================="); - OSD_Printf("Unallocated heap space remaining = %d",i); - OSD_Printf("Unallocated heap space used = %d",ActualHeap - i); - FreeMem(testheap); - i=0; // Beam us out of here Scotty! - } - } - - if(ActualHeap < 50000L) - { - OSD_Printf("ALERT: Memory is critically low!"); - } - */ -} - -int TileRangeMem(int start) -{ - int i; - int total=0; - - switch (start) - { - case 4096: // Evil Ninja - for (i=4096; i<=4239; i++) - total += tilesiz[i].x*tilesiz[i].y; - break; - case 800: // Hornet - for (i=800; i<=811; i++) - total += tilesiz[i].x*tilesiz[i].y; - break; - case 817: - for (i=817; i<=819; i++) // Bouncing Betty - total += tilesiz[i].x*tilesiz[i].y; - break; - case 820: // Skull - for (i=820; i<=854; i++) - total += tilesiz[i].x*tilesiz[i].y; - break; - case 960: - for (i=960; i<=1016; i++) // Serpent God - total += tilesiz[i].x*tilesiz[i].y; - for (i=1300; i<=1314; i++) - total += tilesiz[i].x*tilesiz[i].y; - break; - case 1024: - for (i=1024; i<=1175; i++) // LoWang - total += tilesiz[i].x*tilesiz[i].y; - break; - case 1320: - for (i=1320; i<=1396; i++) // Skeletor Priest - total += tilesiz[i].x*tilesiz[i].y; - break; - case 1400: - for (i=1400; i<=1440; i++) // Coolie - total += tilesiz[i].x*tilesiz[i].y; - for (i=4260; i<=4266; i++) - total += tilesiz[i].x*tilesiz[i].y; - break; - case 1441: - for (i=1441; i<=1450; i++) // Coolie Ghost - total += tilesiz[i].x*tilesiz[i].y; - for (i=4267; i<=4312; i++) - total += tilesiz[i].x*tilesiz[i].y; - break; - case 1469: - for (i=1469; i<=1497; i++) // Guardian - total += tilesiz[i].x*tilesiz[i].y; - for (i=1504; i<=1518; i++) - total += tilesiz[i].x*tilesiz[i].y; - break; - case 1580: - for (i=1580; i<=1644; i++) // Little Ripper - total += tilesiz[i].x*tilesiz[i].y; - break; - case 4320: - for (i=4320; i<=4427; i++) // Big Ripper - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2540: - for (i=2540; i<=2546; i++) // Trashcan - total += tilesiz[i].x*tilesiz[i].y; - break; - case 4430: - for (i=4430; i<=4479; i++) // Fish - total += tilesiz[i].x*tilesiz[i].y; - break; - case 4490: - for (i=4490; i<=4544; i++) // Sumo - total += tilesiz[i].x*tilesiz[i].y; - break; - case 5023: - for (i=5023; i<=5026; i++) // Toilet Girl - total += tilesiz[i].x*tilesiz[i].y; - break; - case 5032: - for (i=5032; i<=5035; i++) // Wash Girl - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2000: - for (i=2000; i<=2002; i++) // Chop Stick Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2004: - for (i=2004; i<=2009; i++) // Uzi Panel - total += tilesiz[i].x*tilesiz[i].y; - for (i=2040; i<=2043; i++) // Uzi Overlays - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2010: - for (i=2010; i<=2019; i++) // Rail Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2130: - for (i=2130; i<=2137; i++) // Shuriken Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2050: - for (i=2050; i<=2053; i++) // Heart Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2054: - for (i=2054; i<=2057; i++) // HotHead Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2070: - for (i=2070; i<=2077; i++) // Rocket Launcher Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2080: - for (i=2080; i<=2083; i++) // Sword Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 4090: - for (i=4090; i<=4093; i++) // Bloody Sword Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2121: - for (i=2121; i<=2126; i++) // 40MM Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2211: - for (i=2211; i<=2216; i++) // Shotgun Panel - total += tilesiz[i].x*tilesiz[i].y; - for (i=2225; i<=2227; i++) // Shotgun Quad-Mode Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - case 2220: - for (i=2220; i<=2224; i++) // Sticky Bomb Panel - total += tilesiz[i].x*tilesiz[i].y; - break; - } - - return total; -} - -void CON_Cache(void) -{ - char incache[MAXTILES]{}; - int i,j,tottiles,totsprites,totactors; - - // Calculate all level tiles, non-actor stuff - for (i=0; i= 0) - incache[wall[i].overpicnum] = 1; - } - - tottiles = 0; - for (i=0; i 0) - tottiles += tilesiz[i].x*tilesiz[i].y; - - ////////////////////////////////////////////// - - memset(incache, 0, sizeof(incache)); - - // Sprites on the stat list get counted as cached, others don't - for (i=0; i 0) - { - switch (i) - { - case 4096: - totactors+=TileRangeMem(4096); - incache[4096]=0; - break; - case 800: - totactors+=TileRangeMem(800); - incache[800]=0; - break; - case 817: - totactors+=TileRangeMem(817); - incache[817]=0; - break; - case 820: - totactors+=TileRangeMem(820); - incache[820]=0; - break; - case 960: - totactors+=TileRangeMem(960); - incache[960]=0; - break; - //case 1024: // Lo Wang is calculated later - // totactors+=TileRangeMem(1024); - // incache[1024]=0; - //break; - case 1320: - totactors+=TileRangeMem(1320); - incache[1320]=0; - break; - case 1400: - totactors+=TileRangeMem(1400); - incache[1400]=0; - break; - case 1441: - totactors+=TileRangeMem(1441); - incache[1441]=0; - break; - case 1469: - totactors+=TileRangeMem(1469); - incache[1469]=0; - break; - case 1580: - totactors+=TileRangeMem(1580); - incache[1580]=0; - break; - case 4320: - totactors+=TileRangeMem(4320); - incache[4320]=0; - break; - case 2540: - totactors+=TileRangeMem(2540); - incache[2540]=0; - break; - case 4430: - totactors+=TileRangeMem(4430); - incache[4430]=0; - break; - case 4490: - totactors+=TileRangeMem(4490); - incache[4490]=0; - break; - case 5023: - totactors+=TileRangeMem(5023); - incache[5023]=0; - break; - case 5032: - totactors+=TileRangeMem(5032); - incache[5032]=0; - break; - case 2000: - totactors+=TileRangeMem(2000); - incache[2000]=0; - break; - case 2004: - totactors+=TileRangeMem(2004); - incache[2004]=0; - break; - case 2010: - totactors+=TileRangeMem(2010); - incache[2010]=0; - break; - case 2130: - totactors+=TileRangeMem(2130); - incache[2130]=0; - break; - case 2050: - totactors+=TileRangeMem(2050); - incache[2050]=0; - break; - case 2054: - totactors+=TileRangeMem(2054); - incache[2054]=0; - break; - case 2070: - totactors+=TileRangeMem(2070); - incache[2070]=0; - break; - case 2080: - totactors+=TileRangeMem(2080); - incache[2080]=0; - break; - case 4090: - totactors+=TileRangeMem(4090); - incache[4090]=0; - break; - case 2121: - totactors+=TileRangeMem(2121); - incache[2121]=0; - break; - case 2211: - totactors+=TileRangeMem(2211); - incache[2211]=0; - break; - case 2220: - totactors+=TileRangeMem(2220); - incache[2220]=0; - break; - - default: totsprites += tilesiz[i].x*tilesiz[i].y; - } - } - } - - OSD_Printf("/////////////////////////////////////////////"); - OSD_Printf("Current Memory Consumption:"); - OSD_Printf("Total Tiles = %d",tottiles); - OSD_Printf("Total Sprites = %d",totsprites); - OSD_Printf("Total Actors = %d",totactors); - OSD_Printf("Total Memory = %d",(tottiles+totsprites+totactors)); - OSD_Printf("Total with LoWang = %d",(tottiles+totsprites+totactors+TileRangeMem(1024))); - OSD_Printf("/////////////////////////////////////////////"); - -} - -void CON_SpriteInfo(void) -{ - SpriteInfo++; - if (SpriteInfo > 2) SpriteInfo = 0; - - if (SpriteInfo == 0) - OSD_Printf("Sprite information is OFF."); - else if (SpriteInfo == 1) - OSD_Printf("Sprite information is ON (Brief Mode)."); - else - OSD_Printf("Sprite information is ON (Verbose Mode)."); -} - -void CON_KillSprite(void) -{ - char base[80]; - int16_t op1=0; - SPRITEp sp; - short i; - USERp u; - - // Format: kill [SpriteNum] - if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) - { - strcpy(MessageInputString,"help kill"); - CON_GetHelp(); - return; - } - - if (op1 == -1) - { - for (i=0; iPlayerP) - SetSuicide(i); - } - OSD_Printf("Killed all sprites except Players."); - } - else - { - if (!CheckValidSprite(op1)) return; - - SetSuicide(op1); - OSD_Printf("Killed sprite %d.",op1); - } - -} - -void CON_SpriteDetail(void) -{ - char base[80]; - int16_t op1=0; - short i; - - // Format: showsprite [SpriteNum] - if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) - { - strcpy(MessageInputString,"help showsprite"); - CON_GetHelp(); - return; - } - - if (!CheckValidSprite(op1)) return; - auto const sp = (uspritetype const *)&sprite[op1]; - - OSD_Printf("x = %d, y = %d, z = %d",sp->x,sp->y,sp->z); - OSD_Printf("cstat = %d, picnum = %d",sp->cstat,sp->picnum); - OSD_Printf("shade = %d, pal = %d, clipdist = %d",sp->shade,sp->pal,sp->clipdist); - OSD_Printf("xrepeat = %d, yrepeat = %d",sp->xrepeat, sp->yrepeat); - OSD_Printf("xoffset = %d, yoffset = %d",sp->xoffset, sp->yoffset); - OSD_Printf("sectnum = %d, statnum = %d",sp->sectnum, sp->statnum); - OSD_Printf("ang = %d, owner = %d",sp->ang,sp->owner); - OSD_Printf("xvel = %d, yvel = %d, zvel = %d",sp->xvel,sp->yvel,sp->zvel); - OSD_Printf("lotag = %d, hitag = %d, extra = %d",sp->lotag,sp->hitag,sp->extra); -} - -void CON_UserDetail(void) -{ - char base[80]; - int16_t op1=0; - SPRITEp sp; - short i; - USERp u; - - // Format: showuser [SpriteNum] - if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) - { - strcpy(MessageInputString,"help showsprite"); - CON_GetHelp(); - return; - } - - if (!CheckValidSprite(op1)) return; - sp = &sprite[op1]; - u = User[op1]; - - if (!u) return; - - OSD_Printf("State = %p, Rot = %p",u->State,u->Rot); - OSD_Printf("StateStart = %p, StateEnd = %p",u->StateStart,u->StateEnd); - OSD_Printf("ActorActionFunc = %p",u->ActorActionFunc); - OSD_Printf("ActorActionSet = %p",u->ActorActionSet); - OSD_Printf("Personality = %p",u->Personality); - OSD_Printf("Attrib = %p",u->Attrib); - OSD_Printf("Flags = %d, Flags2 = %d, Tics = %d",u->Flags,u->Flags2,u->Tics); - OSD_Printf("RotNum = %d, ID = %d",u->RotNum,u->ID); - OSD_Printf("Health = %d, MaxHealth = %d",u->Health,u->MaxHealth); - OSD_Printf("LastDamage = %d, PainThreshold = %d",u->LastDamage,u->PainThreshold); - OSD_Printf("jump_speed = %d, jump_grav = %d",u->jump_speed,u->jump_grav); - OSD_Printf("xchange = %d, ychange = %d, zchange = %d",u->xchange,u->ychange,u->zchange); - OSD_Printf("ret = %d, WaitTics = %d, spal = %d",u->ret,u->WaitTics,u->spal); -} - -void CON_Quit(void) -{ - if (CommPlayers >= 2) - MultiPlayQuitFlag = TRUE; - else - QuitFlag = TRUE; -} - -void CON_MultiNameChange(void) -{ - char base[16],command[16]; - - // Format: swname [name] - if (sscanf(MessageInputString,"%6s %12s",base,command) < 2) - return; - - SendMulitNameChange(command); -} - -void CON_LoadSetup(void) -{ - OSD_Printf("JonoF: Maybe later"); -} - -const char *damagename[] = -{ - "WPN_STAR","WPN_UZI", - "WPN_SHOTGUN","WPN_MICRO", - "WPN_GRENADE","WPN_MINE", - "WPN_RAIL","WPN_HEART", - "WPN_HOTHEAD","WPN_NAPALM" - "WPN_RING","WPN_ROCKET", - "WPN_SWORD","WPN_FIST", - "DMG_NAPALM","DMG_MIRV_METEOR", - "DMG_SERP_METEOR","DMG_ELECTRO_SHARD", - "DMG_SECTOR_EXP","DMG_BOLT_EXP", - "DMG_TANK_SHELL_EXP","DMG_FIREBALL_EXP", - "DMG_NAPALM_EXP","DMG_SKULL_EXP", - "DMG_BASIC_EXP","DMG_GRENADE_EXP", - "DMG_MINE_EXP","DMG_MINE_SHRAP", - "DMG_MICRO_EXP","DMG_NUCLEAR_EXP", - "DMG_RADIATION_CLOUD","DMG_FLASHBOMB", - "DMG_FIREBALL_FLAMES","DMG_RIPPER_SLASH", - "DMG_SKEL_SLASH","DMG_COOLG_BASH", - "DMG_COOLG_FIRE","DMG_GORO_CHOP", - "DMG_GORO_FIREBALL","DMG_SERP_SLASH", - "DMG_LAVA_BOULDER","DMG_LAVA_SHARD", - "DMG_HORNET_STING","DMG_EEL_ELECTRO", - "DMG_SPEAR_TRAP","DMG_VOMIT", - "DMG_BLADE" -}; - -void CON_DamageData(void) -{ - - char base[80],field[80]; - int16_t op1=0; - unsigned int op2, i; - - // Format: damage [field] [item] [value] - if (sscanf(MessageInputString,"%s %s %hd %u",base,field,&op1,&op2) < 3) - { - strcpy(MessageInputString,"help damage"); - CON_GetHelp(); - return; - } - - if (op1 < -1 || op1 > 46) - { - OSD_Printf("Damage Data index is out of range."); - return; - } - - if (!strcmp(field,"damage_lo")) - { - DamageData[op1].damage_lo = op2; - OSD_Printf("DamageData[%s].damage_lo = %d",damagename[op1],op2); - } - else if (!strcmp(field,"damage_hi")) - { - DamageData[op1].damage_hi = op2; - OSD_Printf("DamageData[%s].damage_hi = %d",damagename[op1],op2); - } - else if (!strcmp(field,"radius")) - { - DamageData[op1].radius = op2; - OSD_Printf("DamageData[%s].radius = %d",damagename[op1],op2); - } - else if (!strcmp(field,"max_ammo")) - { - DamageData[op1].max_ammo = op2; - OSD_Printf("DamageData[%s].max_ammo = %d",damagename[op1],op2); - } - else if (!strcmp(field,"min_ammo")) - { - DamageData[op1].min_ammo = op2; - OSD_Printf("DamageData[%s].min_ammo = %d",damagename[op1],op2); - } - if (!strcmp(field,"show")) - { - if (op1 == -1) - { - for (i=op2; i<=op2+10; i+=2) - { - if (i<47) - OSD_Printf("[%d] = %s [%d] = %s",i,damagename[i],i+1,damagename[i+1]); - } - } - else - { - OSD_Printf(" "); - OSD_Printf("Item = %s:",damagename[op1]); - OSD_Printf("damage_lo = %d, damag_hi = %d",DamageData[op1].damage_lo,DamageData[op1].damage_hi); - OSD_Printf("radius = %u",DamageData[op1].radius); - OSD_Printf("min_ammo = %d, max_ammo = %d",DamageData[op1].min_ammo,DamageData[op1].max_ammo); - OSD_Printf(" "); - } - } -} - -void CON_WinPachinko(void) -{ - extern SWBOOL Pachinko_Win_Cheat; - PLAYERp pp = Player + myconnectindex; - extern void CheckSndData(char *file, int line); - - if (CommEnabled) - return; - - Pachinko_Win_Cheat = !Pachinko_Win_Cheat; - - //CheckSndData( __FILE__, __LINE__ ); - - if (Pachinko_Win_Cheat) - PutStringInfo(pp,"Pachinko Win Cheat Enabled"); - else - PutStringInfo(pp,"Pachinko Win Cheat Disabled"); -} - -void CON_Tweak(void) -{ - char base[80], command[80]; - int op1=0; - - // Format: tweak [weapon] [number] - if (sscanf(MessageInputString,"%s %s %d",base,command,&op1) < 3) - { - strcpy(MessageInputString,"help tweak"); - CON_GetHelp(); - return; - } - - Bstrlwr(command); // Make sure operator is all lower case - if (!strcmp(command,"adjust")) - { - extern short ADJUST; - ADJUST = op1; - OSD_Printf("Zvelocity ADJUST set to %d.",op1); - } - else if (!strcmp(command,"adjustv")) - { - extern int ADJUSTV; - ADJUSTV = op1; - OSD_Printf("Zvelocity ADJUSTV set to %d.",op1); - } -} - void CON_Bunny(void) { PLAYERp pp = Player + myconnectindex; @@ -1271,70 +401,6 @@ void CON_Bunny(void) PutStringInfo(pp,"Bunny rockets disabled!"); } -void CON_CheckHeap(void) -{ - /* - switch( _heapchk() ) - { - case _HEAPOK: - OSD_Printf( "OK - heap is good\n" ); - break; - case _HEAPEMPTY: - OSD_Printf( "OK - heap is empty\n" ); - break; - case _HEAPBADBEGIN: - OSD_Printf( "ERROR - heap is damaged\n" ); - break; - case _HEAPBADNODE: - OSD_Printf( "ERROR - bad node in heap\n" ); - break; - } - */ - OSD_Printf("JonoF: Not now"); -} - -/* -void heap_dump( void ) - { - struct _heapinfo h_info; - int heap_status; - - h_info._pentry = NULL; - for(;;) { - heap_status = _heapwalk( &h_info ); - if( heap_status != _HEAPOK ) break; - printf( " %s block at %Fp of size %4.4X\n", - (h_info._useflag == _USEDENTRY ? "USED" : "FREE"), - h_info._pentry, h_info._size ); - - } - - switch( heap_status ) { - case _HEAPEND: - printf( "OK - end of heap\n" ); - break; - case _HEAPEMPTY: - printf( "OK - heap is empty\n" ); - break; - case _HEAPBADBEGIN: - printf( "ERROR - heap is damaged\n" ); - break; - case _HEAPBADPTR: - printf( "ERROR - bad pointer to heap\n" ); - break; - case _HEAPBADNODE: - - printf( "ERROR - bad node in heap\n" ); - } - } - */ - -void CON_DumpHeap(void) -{ - //heap_dump(); // Dump it. - OSD_Printf("JonoF: Not now"); -} - void CON_ShowMirror(void) { char base[80]; @@ -1344,7 +410,6 @@ void CON_ShowMirror(void) if (sscanf(MessageInputString,"%s %hd",base,&op1) < 2) { strcpy(MessageInputString,"help showmirror"); - CON_GetHelp(); return; } @@ -1367,13 +432,5 @@ void CON_ShowMirror(void) OSD_Printf("mirror[%d].iscamera = %d",op1,mirror[op1].ismagic); } -void CON_DumpSoundList(void) -{ - extern void DumpSounds(void); - - DumpSounds(); - OSD_Printf("Sounds dumped to dbg.foo"); - -} END_SW_NS diff --git a/source/sw/src/coolg.cpp b/source/sw/src/coolg.cpp index 0dc518e22..07a76f86f 100644 --- a/source/sw/src/coolg.cpp +++ b/source/sw/src/coolg.cpp @@ -850,7 +850,7 @@ int DoCoolgMove(short SpriteNum) u->ShellNum = SEC(2); break; case 1: - PlaySound(DIGI_VOID3, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_VOID3, sp, v3df_follow); RESET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); SET(sp->cstat, CSTAT_SPRITE_INVISIBLE); u->ShellNum = SEC(1) + SEC(RANDOM_RANGE(2)); @@ -861,7 +861,7 @@ int DoCoolgMove(short SpriteNum) u->ShellNum = SEC(2); break; case 3: - PlaySound(DIGI_VOID3, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_VOID3, sp, v3df_follow); RESET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); u->ShellNum = SEC(2) + SEC(RANDOM_RANGE(3)); diff --git a/source/sw/src/coolie.cpp b/source/sw/src/coolie.cpp index 2280b53f1..4d72945a4 100644 --- a/source/sw/src/coolie.cpp +++ b/source/sw/src/coolie.cpp @@ -662,7 +662,7 @@ int InitCoolieCharge(short SpriteNum) USERp u = User[SpriteNum]; if (RANDOM_P2(1024) > 950) - PlaySound(DIGI_COOLIESCREAM, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_COOLIESCREAM, sp, v3df_follow); DoActorSetSpeed(SpriteNum, FAST_SPEED); diff --git a/source/sw/src/d_menu.cpp b/source/sw/src/d_menu.cpp index 3c431eabc..f725c8d8c 100644 --- a/source/sw/src/d_menu.cpp +++ b/source/sw/src/d_menu.cpp @@ -33,20 +33,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "weapon.h" #include "player.h" #include "jsector.h" -#include "control.h" #include "menus.h" #include "sw_strs.h" #include "pal.h" #include "demo.h" -#include "input.h" #include "keydef.h" #include "gamecontrol.h" #include "gamedefs.h" #include "config.h" #include "network.h" -#include "fx_man.h" -#include "music.h" #include "text.h" #include "version.h" #include "network.h" @@ -54,6 +50,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "colormap.h" #include "config.h" #include "menu/menu.h" +#include "sound/s_soundinternal.h" +#include "sounds.h" #include "../../glbackend/glbackend.h" @@ -110,9 +108,9 @@ public: DidOrderSound = true; int choose_snd = STD_RANDOM_RANGE(1000); if (choose_snd > 500) - PlaySound(DIGI_WANGORDER1, &zero, &zero, &zero, v3df_dontpan); + PlaySound(DIGI_WANGORDER1, v3df_dontpan); else - PlaySound(DIGI_WANGORDER2, &zero, &zero, &zero, v3df_dontpan); + PlaySound(DIGI_WANGORDER2, v3df_dontpan); } } }; @@ -180,15 +178,15 @@ void GameInterface::MenuSound(EMenuSounds snd) switch (snd) { case CursorSound: - PlaySound(DIGI_STAR,&zero,&zero,&zero,v3df_dontpan); + PlaySound(DIGI_STAR, v3df_dontpan); break; case AdvanceSound: - PlaySound(DIGI_SWORDSWOOSH,&zero,&zero,&zero,v3df_dontpan); + PlaySound(DIGI_SWORDSWOOSH, v3df_dontpan); break; case CloseSound: - PlaySound(DIGI_STARCLINK,&zero,&zero,&zero,v3df_dontpan); + PlaySound(DIGI_STARCLINK, v3df_dontpan); break; default: @@ -239,17 +237,19 @@ void GameInterface::StartGame(FGameStartup& gs) //InitNewGame(); if (Skill == 0) - handle = PlaySound(DIGI_TAUNTAI3,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_TAUNTAI3, v3df_none, CHAN_VOICE); else if (Skill == 1) - handle = PlaySound(DIGI_NOFEAR,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_NOFEAR, v3df_none, CHAN_VOICE); else if (Skill == 2) - handle = PlaySound(DIGI_WHOWANTSWANG,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_WHOWANTSWANG, v3df_none, CHAN_VOICE); else if (Skill == 3) - handle = PlaySound(DIGI_NOPAIN,&zero,&zero,&zero,v3df_none); + PlaySound(DIGI_NOPAIN, v3df_none, CHAN_VOICE); - if (handle > FX_Ok) - while (FX_SoundActive(handle)) - handleevents(); + while (soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, CHAN_VOICE)) + { + DoUpdateSounds(); + handleevents(); + } } FSavegameInfo GameInterface::GetSaveSig() diff --git a/source/sw/src/demo.cpp b/source/sw/src/demo.cpp index 863214725..7fc518b16 100644 --- a/source/sw/src/demo.cpp +++ b/source/sw/src/demo.cpp @@ -28,7 +28,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms //#define MAIN //#define QUIET #include "build.h" -#include "cache1d.h" + #include "keys.h" #include "names2.h" @@ -37,7 +37,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "network.h" #include "mytypes.h" -#include "control.h" #include "gamecontrol.h" #include "demo.h" diff --git a/source/sw/src/draw.cpp b/source/sw/src/draw.cpp index 930165ce2..ad53274fc 100644 --- a/source/sw/src/draw.cpp +++ b/source/sw/src/draw.cpp @@ -28,7 +28,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #define QUIET #include "build.h" #include "pragmas.h" -#include "cache1d.h" + #include "keys.h" #include "names2.h" @@ -40,7 +40,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "jsector.h" #include "mytypes.h" -#include "control.h" #include "gamecontrol.h" #include "network.h" #include "pal.h" diff --git a/source/sw/src/game.cpp b/source/sw/src/game.cpp index 3ba3a4ecc..aad9ccb37 100644 --- a/source/sw/src/game.cpp +++ b/source/sw/src/game.cpp @@ -44,7 +44,7 @@ Things required to make savegames work: #define QUIET #include "build.h" #include "baselayer.h" -#include "cache1d.h" + #include "osd.h" #include "renderlayer.h" @@ -60,7 +60,6 @@ Things required to make savegames work: #include "lists.h" #include "network.h" #include "pal.h" -#include "fx_man.h" #include "input.h" #include "mytypes.h" @@ -68,7 +67,6 @@ Things required to make savegames work: #include "menus.h" -#include "control.h" #include "gamecontrol.h" #include "gamedefs.h" #include "config.h" @@ -85,9 +83,7 @@ Things required to make savegames work: #include "light.h" #include "track.h" #include "jsector.h" -#include "keyboard.h" #include "text.h" -#include "music.h" #include "common.h" #include "common_game.h" @@ -100,6 +96,7 @@ Things required to make savegames work: #include "statistics.h" #include "gstrings.h" #include "mapinfo.h" +#include "sound/s_soundinternal.h" //#include "crc32.h" @@ -135,7 +132,9 @@ SWBOOL Global_PLock = TRUE; SWBOOL Global_PLock = FALSE; #endif -int GameVersion = 13; // 12 was original source release. For future releases increment by two. +// 12 was original source release. For future releases increment by two. +int GameVersion = 15; + char DemoText[3][64]; int DemoTextYstart = 0; @@ -276,7 +275,6 @@ int krandcount; void BOT_DeleteAllBots(void); void BotPlayerInsert(PLAYERp pp); void SybexScreen(void); -void DosScreen(void); void PlayTheme(void); void MenuLevel(void); void StatScreen(PLAYERp mpp); @@ -636,14 +634,8 @@ void TerminateGame(void) engineUnInit(); - //Terminate3DSounds(); // Kill the sounds linked list - UnInitSound(); - timerUninit(); - - if (CleanExit) - DosScreen(); - + Bexit(0); } bool LoadLevel(const char *filename) @@ -722,7 +714,7 @@ void MultiSharewareCheck(void) if (!SW_SHAREWARE) return; if (numplayers > 4) { -#ifdef RENDERTYPEWIN +#if 1 /* defined RENDERTYPEWIN */ wm_msgbox(apptitle,"To play a Network game with more than 4 players you must purchase " "the full version. Read the Ordering Info screens for details."); #else @@ -733,7 +725,6 @@ void MultiSharewareCheck(void) //uninitmultiplayers(); //uninitkeys(); engineUnInit(); - UnInitSound(); timerUninit(); Bexit(0); } @@ -795,7 +786,6 @@ void COVERsetbrightness(int bright, unsigned char *pal) static int firstnet = 0; // JBF -int nextvoxid = 0; // JBF static void SW_FatalEngineError(void) @@ -935,6 +925,8 @@ bool InitGame() if (enginePostInit()) SW_FatalEngineError(); + palettePostLoadLookups(); + DemoModeMenuInit = TRUE; // precache as much stuff as you can if (UserMapName[0] == '\0') @@ -1319,9 +1311,7 @@ TerminateLevel(void) memset(Track, 0, sizeof(Track)); StopSound(); - Terminate3DSounds(); // Kill the 3d sounds linked list - //ClearSoundLocks(); - + // Clear all anims and any memory associated with them // Clear before killing sprites - save a little time //AnimClear(); @@ -1403,7 +1393,6 @@ void NewLevel(void) { if (DemoPlaying) { - FX_SetVolume(0); // Shut the hell up while game is loading! InitLevel(); InitRunLevel(); @@ -1426,7 +1415,6 @@ void NewLevel(void) } else { - FX_SetVolume(0); // Shut the hell up while game is loading! InitLevel(); RunLevel(); STAT_Update(false); @@ -1531,9 +1519,6 @@ void LogoLevel(void) DSPRINTF(ds,"LogoLevel..."); MONO_PRINT(ds); - // PreCache Anim - LoadAnm(0, &fin); - auto pal = fileSystem.LoadFile("3drealms.pal", 0); if (pal.Size() >= 768) { @@ -1615,19 +1600,24 @@ void CreditsLevel(void) videoNextPage(); // Lo Wang feel like singing! - handle = PlaySound(DIGI_JG95012,&zero,&zero,&zero,v3df_none); - - if (handle > 0) - while (FX_SoundActive(handle)) ; + PlaySound(DIGI_JG95012, v3df_none, CHAN_VOICE); + while (soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, CHAN_VOICE)) + { + DoUpdateSounds(); + handleevents(); + } // try 14 then 2 then quit if (!PlaySong(nullptr, ThemeSongs[5], ThemeTrack[5], true)) { if (!PlaySong(nullptr, nullptr, 2, true)) { - handle = PlaySound(DIGI_NOLIKEMUSIC,&zero,&zero,&zero,v3df_none); - if (handle > 0) - while (FX_SoundActive(handle)) handleevents(); + PlaySound(DIGI_NOLIKEMUSIC, v3df_none, CHAN_VOICE); + while (soundEngine->IsSourcePlayingSomething(SOURCE_None, nullptr, CHAN_VOICE)) + { + DoUpdateSounds(); + handleevents(); + } return; } } @@ -1915,6 +1905,7 @@ void MenuLevel(void) //drawscreen as fast as you can DrawMenuLevelScreen(); + DoUpdateSounds(); videoNextPage(); } @@ -2014,21 +2005,21 @@ void gStateControl(STATEp *State, int *tics) int BonusPunchSound(short SpriteNum) { PLAYERp pp = Player + myconnectindex; - PlaySound(DIGI_PLAYERYELL3, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_PLAYERYELL3, pp, v3df_none); return 0; } int BonusKickSound(short SpriteNum) { PLAYERp pp = Player + myconnectindex; - PlaySound(DIGI_PLAYERYELL2, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_PLAYERYELL2, pp, v3df_none); return 0; } int BonusGrabSound(short SpriteNum) { PLAYERp pp = Player + myconnectindex; - PlaySound(DIGI_BONUS_GRAB, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_BONUS_GRAB, pp, v3df_none); return 0; } @@ -2266,7 +2257,6 @@ void BonusScreen(PLAYERp pp) } StopSound(); - Terminate3DSounds(); } void EndGameSequence(void) @@ -2482,7 +2472,6 @@ void StatScreen(PLAYERp mpp) } StopSound(); - Terminate3DSounds(); } void GameIntro(void) @@ -2547,7 +2536,7 @@ void _Assert(const char *expr, const char *strFile, unsigned uLine) TerminateGame(); -#if 1 //def RENDERTYPEWIN +#if 1 /* defined RENDERTYPEWIN */ wm_msgbox(apptitle, "%s", ds); #else printf("Assertion failed: %s\n %s, line %u\n", expr, strFile, uLine); @@ -2564,7 +2553,7 @@ void _ErrMsg(const char *strFile, unsigned uLine, const char *format, ...) //MONO_PRINT(ds); TerminateGame(); -#if 1 //def RENDERTYPEWIN +#if 1 /* defined RENDERTYPEWIN */ { char msg[256], *p; Bsnprintf(msg, sizeof(msg), "Error: %s, line %u\n", strFile, uLine); @@ -2751,9 +2740,6 @@ void InitRunLevel(void) SetRedrawScreen(Player + myconnectindex); - snd_reversestereo.Callback(); - snd_fxvolume.Callback(); - FX_SetVolume(snd_fxvolume); // Turn volume back up if (snd_ambience) StartAmbientSound(); } @@ -2765,8 +2751,6 @@ void RunLevel(void) int i; InitRunLevel(); - FX_SetVolume(snd_fxvolume); - #if 0 waitforeverybody(); #endif @@ -2797,15 +2781,6 @@ void RunLevel(void) ready2send = 0; } -void swexit(int exitval) -{ - exit(exitval); -} - -void DosScreen(void) -{ -} - typedef struct { char notshareware; @@ -2815,20 +2790,7 @@ typedef struct const char *arg_descr; } CLI_ARG; -#if DEBUG -CLI_ARG cli_dbg_arg[] = -{ - {0, "/demosyncrecord", 13, "-demosyncrecord", "Demo sync record" }, - {0, "/demosynctest", 13, "-demosynctest", "Demo sync test" }, - {0, "/cam", 4, "-cam", "Camera test mode" }, - {0, "/debugactor", 11, "-debugactor", "No Actors" }, - {0, "/debuganim", 10, "-debuganim", "No Anims" }, - {0, "/debugso", 8, "-debugso", "No Sector Objects" }, - {0, "/debugsector", 12, "-debugsector", "No Sector Movement" }, - {0, "/debugpanel", 11, "-debugpanel", "No Panel" }, - {0, "/mono", 5, "-mono", "Mono" }, -}; -#endif + CLI_ARG cli_arg[] = @@ -2920,6 +2882,7 @@ int32_t GameInterface::app_main() { I_Error("There was a problem initialising the Build engine: %s", engineerrstr); } + hud_size.Callback(); if (!DetectShareware()) { diff --git a/source/sw/src/game.h b/source/sw/src/game.h index e27bffb0d..d2875efa0 100644 --- a/source/sw/src/game.h +++ b/source/sw/src/game.h @@ -41,7 +41,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "mmulti.h" #include "mytypes.h" -#include "keyboard.h" #include "sounds.h" #include "settings.h" #include "pragmas.h" @@ -1205,16 +1204,12 @@ struct PLAYERstruct SWBOOL IsAI; // Is this and AI character? short fta,ftq; // First time active and first time quote, for talking in multiplayer games short NumFootPrints; // Number of foot prints left to lay down - SWBOOL PlayerTalking; // Is player currently talking - int TalkVocnum; // Number of sound that player is using - int TalkVocHandle; // Handle of sound in sound queue, to access in Dose's code unsigned char WpnUziType; // Toggle between single or double uzi's if you own 2. unsigned char WpnShotgunType; // Shotgun has normal or fully automatic fire unsigned char WpnShotgunAuto; // 50-0 automatic shotgun rounds unsigned char WpnShotgunLastShell; // Number of last shell fired unsigned char WpnRailType; // Normal Rail Gun or EMP Burst Mode SWBOOL Bloody; // Is player gooey from the slaughter? - int nukevochandle; // Stuff for the Nuke SWBOOL InitingNuke; SWBOOL TestNukeInit; SWBOOL NukeInitialized; // Nuke already has counted down @@ -2071,11 +2066,50 @@ short ActorFindTrack(short SpriteNum, int8_t player_dir, int track_type, short * SECT_USERp GetSectUser(short sectnum); +// Some sounds were checked by storing handles in static local variables. +// Problems with this design: +// 1. The variables were unmaintained and could refer to handles that had been reused already. +// 2. No proper sound ownership tracking. +// 3. In some cases items that were supposed to use the same check referred to different handle variables. +// In short: I was very broken. This is a list of all sound items used this way, now each one gets a dedicated channel +// so that proper checks can be performed and sound ownership be tracked. + +enum +{ + CHAN_ToiletFart = 1000, + CHAN_AnimeMad = 1001, + CHAN_AnimeSing = 1002, + CHAN_CoyHandle = 1003, + CHAN_RipHeart = 1004, +}; + short SoundDist(int x, int y, int z, int basedist); short SoundAngle(int x, int y); //void PlaySound(int num, short angle, short vol); -int PlaySound(int num, int *x, int *y, int *z, Voc3D_Flags flags); -void PlayerSound(int num, int *x, int *y, int *z, Voc3D_Flags flags, PLAYERp pp); +int _PlaySound(int num, SPRITEp sprite, PLAYERp player, vec3_t *pos, Voc3D_Flags flags, int channel); +void InitAmbient(int num, SPRITEp sprite); +inline void PlaySound(int num, SPRITEp sprite, Voc3D_Flags flags, int channel = 8) +{ + _PlaySound(num, sprite, nullptr, nullptr, flags, channel); +} +inline void PlaySound(int num, PLAYERp player, Voc3D_Flags flags, int channel = 8) +{ + _PlaySound(num, nullptr, player, nullptr, flags, channel); +} +inline void PlaySound(int num, Voc3D_Flags flags, int channel = 8) +{ + _PlaySound(num, nullptr, nullptr, nullptr, flags, channel); +} +inline void PlaySound(int num, vec3_t *pos, Voc3D_Flags flags, int channel = 8) +{ + _PlaySound(num, nullptr, nullptr, pos, flags, channel); +} + +int _PlayerSound(int num, PLAYERp pp); +inline int PlayerSound(int num, int flags, PLAYERp pp) { return _PlayerSound(num, pp); } +void StopPlayerSound(PLAYERp pp); +bool SoundValidAndActive(SPRITEp spr, int channel); + ANIMATOR DoActorBeginJump,DoActorJump,DoActorBeginFall,DoActorFall,DoActorDeathMove; @@ -2278,8 +2312,7 @@ extern void DoPaletteFlash(PLAYERp pp); extern unsigned char palette_data[256][3]; extern SWBOOL NightVision; -int _PlayerSound(const char *file, int line, int num, int *x, int *y, int *z, Voc3D_Flags flags, PLAYERp pp); -#define PlayerSound(num, x, y, z, flags, pp) _PlayerSound(__FILE__, __LINE__, (num), (x), (y), (z), (flags), (pp)) + #define MAXSO (INT32_MAX) diff --git a/source/sw/src/hornet.cpp b/source/sw/src/hornet.cpp index cf2f77eff..694ea78a8 100644 --- a/source/sw/src/hornet.cpp +++ b/source/sw/src/hornet.cpp @@ -328,7 +328,7 @@ SetupHornet(short SpriteNum) sp->yrepeat = 32; // Special looping buzz sound attached to each hornet spawned - PlaySound(DIGI_HORNETBUZZ,&sp->x,&sp->y,&sp->z,v3df_follow|v3df_init); + PlaySound(DIGI_HORNETBUZZ, sp, v3df_follow|v3df_init); Set3DSoundOwner(SpriteNum); return 0; diff --git a/source/sw/src/inv.cpp b/source/sw/src/inv.cpp index 5e1fc31f6..5e04d15e6 100644 --- a/source/sw/src/inv.cpp +++ b/source/sw/src/inv.cpp @@ -339,9 +339,9 @@ void UseInventoryMedkit(PLAYERp pp) if (pp == Player+myconnectindex) { if (amt >= 30) - PlayerSound(DIGI_GETMEDKIT,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_GETMEDKIT, v3df_follow|v3df_dontpan,pp); else - PlayerSound(DIGI_AHH,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_AHH, v3df_follow|v3df_dontpan,pp); } } @@ -431,13 +431,13 @@ void UseInventoryRepairKit(PLAYERp pp) SPRITEp sp = pp->SpriteP; short inv = INVENTORY_REPAIR_KIT; - //PlaySound(DIGI_TOOLBOX, &pp->posx, &pp->posy, &pp->posz, v3df_none); + //PlaySound(DIGI_TOOLBOX, pp, v3df_none); if (pp == Player + myconnectindex) { if (STD_RANDOM_RANGE(1000) > 500) - PlayerSound(DIGI_NOREPAIRMAN,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_NOREPAIRMAN, v3df_follow|v3df_dontpan,pp); else - PlayerSound(DIGI_NOREPAIRMAN2,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_NOREPAIRMAN2, v3df_follow|v3df_dontpan,pp); } pp->InventoryPercent[inv] = 0; @@ -475,10 +475,10 @@ void UseInventoryCloak(PLAYERp pp) SET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); sp->shade = 100; - PlaySound(DIGI_GASPOP, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_GASPOP, pp, v3df_none); //if(RANDOM_RANGE(1000) > 950) if (pp == Player+myconnectindex) - PlayerSound(DIGI_IAMSHADOW,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_IAMSHADOW, v3df_follow|v3df_dontpan,pp); } void StopInventoryCloak(PLAYERp pp, short InventoryNum) @@ -500,7 +500,7 @@ void StopInventoryCloak(PLAYERp pp, short InventoryNum) RESET(sp->cstat, CSTAT_SPRITE_TRANSLUCENT); sp->shade = 0; - PlaySound(DIGI_GASPOP, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_GASPOP, pp, v3df_none); } ////////////////////////////////////////////////////////////////////// @@ -540,7 +540,7 @@ void StopInventoryEnvironSuit(PLAYERp pp, short InventoryNum) // on/off PlayerUpdateInventory(pp, InventoryNum); - PlaySound(DIGI_SWCLOAKUNCLOAK, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_SWCLOAKUNCLOAK, pp, v3df_none); } #endif @@ -600,7 +600,7 @@ UseInventoryNightVision(PLAYERp pp) PlayerUpdateInventory(pp, pp->InventoryNum); DoPlayerNightVisionPalette(pp); - PlaySound(DIGI_NIGHTON, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow); + PlaySound(DIGI_NIGHTON, pp, v3df_dontpan|v3df_follow); } void @@ -624,7 +624,7 @@ StopInventoryNightVision(PLAYERp pp, short InventoryNum) DoPlayerNightVisionPalette(pp); DoPlayerDivePalette(pp); - PlaySound(DIGI_NIGHTOFF, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow); + PlaySound(DIGI_NIGHTOFF, pp, v3df_dontpan|v3df_follow); } ////////////////////////////////////////////////////////////////////// diff --git a/source/sw/src/jplayer.cpp b/source/sw/src/jplayer.cpp index 04a9aac35..de7da172b 100644 --- a/source/sw/src/jplayer.cpp +++ b/source/sw/src/jplayer.cpp @@ -43,7 +43,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "common_game.h" #include "gamecontrol.h" -#include "control.h" #include "trigger.h" #include "savedef.h" diff --git a/source/sw/src/jsector.cpp b/source/sw/src/jsector.cpp index 97f4464f1..e56a64056 100644 --- a/source/sw/src/jsector.cpp +++ b/source/sw/src/jsector.cpp @@ -83,7 +83,6 @@ void SpawnWallSound(short sndnum, short i) short SpriteNum; vec3_t mid; SPRITEp sp; - int handle; SpriteNum = COVERinsertsprite(0, STAT_DEFAULT); if (SpriteNum < 0) @@ -99,9 +98,7 @@ void SpawnWallSound(short sndnum, short i) setspritez(SpriteNum, &mid); sp = &sprite[SpriteNum]; - handle = PlaySound(sndnum, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); - if (handle != -1) - Set3DSoundOwner(SpriteNum); + PlaySound(sndnum, sp, v3df_dontpan | v3df_doppler); } short @@ -179,7 +176,6 @@ JS_SpriteSetup(void) short SpriteNum = 0, NextSprite, ndx; USERp u; short i, num; - int handle; TRAVERSE_SPRITE_STAT(headspritestat[0], SpriteNum, NextSprite) @@ -217,8 +213,6 @@ JS_SpriteSetup(void) else if (tag == AMBIENT_SOUND) { change_sprite_stat(SpriteNum, STAT_AMBIENT); - // PlaySound(sp->lotag, &sp->x, &sp->y, &sp->z, v3df_ambient - // | v3df_init | v3df_doppler); } else if (tag == TAG_ECHO_SOUND) { @@ -250,21 +244,14 @@ JS_SpriteSetup(void) case 2720: case 3143: case 3157: - handle = PlaySound(DIGI_FIRE1, &sp->x, &sp->y, &sp->z, v3df_follow|v3df_dontpan|v3df_doppler); - if (handle != -1) - Set3DSoundOwner(SpriteNum); + PlaySound(DIGI_FIRE1, sp, v3df_follow|v3df_dontpan|v3df_doppler); break; case 795: case 880: - handle = PlaySound(DIGI_WATERFLOW1, &sp->x, &sp->y, &sp->z, v3df_follow|v3df_dontpan|v3df_doppler); - if (handle != -1) - Set3DSoundOwner(SpriteNum); + PlaySound(DIGI_WATERFLOW1, sp, v3df_follow|v3df_dontpan|v3df_doppler); break; case 460: // Wind Chimes - handle = PlaySound(79, &sp->x, &sp->y, &sp->z, v3df_ambient | v3df_init - | v3df_doppler | v3df_follow); - if (handle != -1) - Set3DSoundOwner(SpriteNum); + InitAmbient(79, sp); break; } @@ -1353,7 +1340,7 @@ UnlockKeyLock(short key_num, short hit_sprite) case SKEL_LOCKED: if (sp->pal == color) { - PlaySound(DIGI_UNLOCK, &sp->x, &sp->y, &sp->z, v3df_doppler | v3df_dontpan); + PlaySound(DIGI_UNLOCK, sp, v3df_doppler | v3df_dontpan); if (SpriteNum == hit_sprite) sp->picnum = SKEL_UNLOCKED; } @@ -1361,14 +1348,14 @@ UnlockKeyLock(short key_num, short hit_sprite) case RAMCARD_LOCKED: if (sp->pal == color) { - PlaySound(DIGI_CARDUNLOCK, &sp->x, &sp->y, &sp->z, v3df_doppler | v3df_dontpan); + PlaySound(DIGI_CARDUNLOCK, sp, v3df_doppler | v3df_dontpan); sp->picnum = RAMCARD_UNLOCKED; } break; case CARD_LOCKED: if (sp->pal == color) { - PlaySound(DIGI_RAMUNLOCK, &sp->x, &sp->y, &sp->z, v3df_doppler | v3df_dontpan); + PlaySound(DIGI_RAMUNLOCK, sp, v3df_doppler | v3df_dontpan); if (SpriteNum == hit_sprite) sp->picnum = CARD_UNLOCKED; else diff --git a/source/sw/src/jweapon.cpp b/source/sw/src/jweapon.cpp index 823169808..a9b309878 100644 --- a/source/sw/src/jweapon.cpp +++ b/source/sw/src/jweapon.cpp @@ -874,7 +874,7 @@ DoChemBomb(int16_t Weapon) SPRITEp hsp; if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) - PlaySound(DIGI_CHEMBOUNCE, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_CHEMBOUNCE, sp, v3df_dontpan); hit_sprite = NORM_SPRITE(u->ret); hsp = &sprite[hit_sprite]; @@ -890,8 +890,8 @@ DoChemBomb(int16_t Weapon) // Canister pops when first smoke starts out if (u->WaitTics == CHEMTICS && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) { - PlaySound(DIGI_GASPOP, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); - PlaySound(DIGI_CHEMGAS, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_GASPOP, sp, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_CHEMGAS, sp, v3df_dontpan | v3df_doppler); Set3DSoundOwner(Weapon); } u->xchange = u->ychange = 0; @@ -921,7 +921,7 @@ DoChemBomb(int16_t Weapon) } if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) - PlaySound(DIGI_CHEMBOUNCE, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_CHEMBOUNCE, sp, v3df_dontpan); nw = wall[hit_wall].point2; wall_ang = NORM_ANGLE(getangle(wall[nw].x - wph->x, wall[nw].y - wph->y) + 512); @@ -953,7 +953,7 @@ DoChemBomb(int16_t Weapon) if (!TEST(u->Flags, SPR_BOUNCE)) { if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) - PlaySound(DIGI_CHEMBOUNCE, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_CHEMBOUNCE, sp, v3df_dontpan); SET(u->Flags, SPR_BOUNCE); ScaleSpriteVector(Weapon, 32000); // was 18000 u->zchange /= 6; @@ -965,8 +965,8 @@ DoChemBomb(int16_t Weapon) // Canister pops when first smoke starts out if (u->WaitTics == CHEMTICS && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) { - PlaySound(DIGI_GASPOP, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); - PlaySound(DIGI_CHEMGAS, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_GASPOP, sp, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_CHEMGAS, sp, v3df_dontpan | v3df_doppler); Set3DSoundOwner(Weapon); } SpawnRadiationCloud(Weapon); @@ -1000,7 +1000,7 @@ DoChemBomb(int16_t Weapon) if (!TEST(u->Flags, SPR_BOUNCE)) { if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) - PlaySound(DIGI_CHEMBOUNCE, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_CHEMBOUNCE, sp, v3df_dontpan); SET(u->Flags, SPR_BOUNCE); u->ret = 0; u->Counter = 0; @@ -1013,8 +1013,8 @@ DoChemBomb(int16_t Weapon) // Canister pops when first smoke starts out if (u->WaitTics == CHEMTICS && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE)) { - PlaySound(DIGI_GASPOP, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); - PlaySound(DIGI_CHEMGAS, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_GASPOP, sp, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_CHEMGAS, sp, v3df_dontpan | v3df_doppler); Set3DSoundOwner(Weapon); } // WeaponMoveHit(Weapon); @@ -1132,7 +1132,7 @@ DoCaltrops(int16_t Weapon) short hit_sprite; SPRITEp hsp; - PlaySound(DIGI_CALTROPS, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_CALTROPS, sp, v3df_dontpan); hit_sprite = NORM_SPRITE(u->ret); hsp = &sprite[hit_sprite]; @@ -1168,7 +1168,7 @@ DoCaltrops(int16_t Weapon) break; } - PlaySound(DIGI_CALTROPS, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_CALTROPS, sp, v3df_dontpan); nw = wall[hit_wall].point2; wall_ang = NORM_ANGLE(getangle(wall[nw].x - wph->x, wall[nw].y - wph->y) + 512); @@ -1199,7 +1199,7 @@ DoCaltrops(int16_t Weapon) // hit a floor if (!TEST(u->Flags, SPR_BOUNCE)) { - PlaySound(DIGI_CALTROPS, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_CALTROPS, sp, v3df_dontpan); SET(u->Flags, SPR_BOUNCE); ScaleSpriteVector(Weapon, 1000); // was 18000 u->ret = 0; @@ -1236,7 +1236,7 @@ DoCaltrops(int16_t Weapon) if (!TEST(u->Flags, SPR_BOUNCE)) { - PlaySound(DIGI_CALTROPS, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_CALTROPS, sp, v3df_dontpan); SET(u->Flags, SPR_BOUNCE); u->ret = 0; u->Counter = 0; @@ -1387,7 +1387,7 @@ PlayerInitChemBomb(PLAYERp pp) int dist; - PlaySound(DIGI_THROW, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_THROW, pp, v3df_dontpan | v3df_doppler); if (pp->cursectnum < 0) return 0; @@ -1474,7 +1474,7 @@ InitSpriteChemBomb(int16_t SpriteNum) int dist; - PlaySound(DIGI_THROW, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_THROW, sp, v3df_dontpan | v3df_doppler); nx = sp->x; ny = sp->y; @@ -1606,7 +1606,7 @@ PlayerInitFlashBomb(PLAYERp pp) SPRITEp sp = pp->SpriteP, hp; USERp u = User[pp->PlayerSprite], hu; - PlaySound(DIGI_GASPOP, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_GASPOP, pp, v3df_dontpan | v3df_doppler); // Set it just a little to let player know what he just did SetFadeAmt(pp, -30, 1); // White flash @@ -1650,8 +1650,7 @@ PlayerInitFlashBomb(PLAYERp pp) choosesnd = RANDOM_RANGE(MAX_PAIN); - PlayerSound(PlayerLowHealthPainVocs[choosesnd],&pp->posx, - &pp->posy,&pp->posy,v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(PlayerLowHealthPainVocs[choosesnd],v3df_dontpan|v3df_doppler|v3df_follow,pp); } SetFadeAmt(hu->PlayerP, damage, 1); // White flash } @@ -1677,7 +1676,7 @@ InitFlashBomb(int16_t SpriteNum) USERp u = User[SpriteNum], hu; PLAYERp pp = Player + screenpeek; - PlaySound(DIGI_GASPOP, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_GASPOP, sp, v3df_dontpan | v3df_doppler); for (stat = 0; stat < SIZ(StatDamageList); stat++) { @@ -1710,8 +1709,7 @@ InitFlashBomb(int16_t SpriteNum) choosesnd = RANDOM_RANGE(MAX_PAIN); - PlayerSound(PlayerLowHealthPainVocs[choosesnd],&pp->posx, - &pp->posy,&pp->posy,v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(PlayerLowHealthPainVocs[choosesnd],v3df_dontpan|v3df_doppler|v3df_follow,pp); } SetFadeAmt(hu->PlayerP, damage, 1); // White flash } @@ -1835,7 +1833,7 @@ PlayerInitCaltrops(PLAYERp pp) int dist; - PlaySound(DIGI_THROW, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_THROW, pp, v3df_dontpan | v3df_doppler); if (pp->cursectnum < 0) return 0; @@ -1920,7 +1918,7 @@ InitCaltrops(int16_t SpriteNum) int dist; - PlaySound(DIGI_THROW, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_THROW, sp, v3df_dontpan | v3df_doppler); nx = sp->x; ny = sp->y; @@ -1973,7 +1971,7 @@ InitPhosphorus(int16_t SpriteNum) int dist; - PlaySound(DIGI_FIREBALL1, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_FIREBALL1, sp, v3df_follow); nx = sp->x; ny = sp->y; @@ -2042,11 +2040,11 @@ InitBloodSpray(int16_t SpriteNum, SWBOOL dogib, short velocity) // { rnd = RANDOM_RANGE(1000); if (rnd > 650) - PlaySound(DIGI_GIBS1, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_GIBS1, sp, v3df_none); else if (rnd > 350) - PlaySound(DIGI_GIBS2, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_GIBS2, sp, v3df_none); else - PlaySound(DIGI_GIBS3, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_GIBS3, sp, v3df_none); // } ang = sp->ang; @@ -2265,7 +2263,7 @@ DoCarryFlag(int16_t Weapon) } if (!TEST_BOOL1(fp)) { - PlaySound(DIGI_BIGITEM, &ap->x, &ap->y, &ap->z, v3df_none); + PlaySound(DIGI_BIGITEM, ap, v3df_none); DoFlagScore(ap->pal); if (SP_TAG5(fp) > 0) { @@ -2296,55 +2294,55 @@ DoCarryFlag(int16_t Weapon) case 0: if (u->WaitTics < SEC(30)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 1: if (u->WaitTics < SEC(20)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 2: if (u->WaitTics < SEC(10)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 3: if (u->WaitTics < SEC(5)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 4: if (u->WaitTics < SEC(4)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 5: if (u->WaitTics < SEC(3)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 6: if (u->WaitTics < SEC(2)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2 = FLAG_DETONATE_STATE; } break; case FLAG_DETONATE_STATE: // start frantic beeping - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; break; case FLAG_DETONATE_STATE + 1: @@ -2406,7 +2404,7 @@ DoCarryFlagNoDet(int16_t Weapon) } if (!TEST_BOOL1(fp)) { - PlaySound(DIGI_BIGITEM, &ap->x, &ap->y, &ap->z, v3df_none); + PlaySound(DIGI_BIGITEM, ap, v3df_none); DoFlagScore(ap->pal); if (SP_TAG5(fp) > 0) { diff --git a/source/sw/src/menus.cpp b/source/sw/src/menus.cpp index fef2dc1d8..7883f0591 100644 --- a/source/sw/src/menus.cpp +++ b/source/sw/src/menus.cpp @@ -38,7 +38,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "weapon.h" #include "player.h" #include "jsector.h" -#include "control.h" #include "menus.h" #include "sw_strs.h" #include "pal.h" @@ -50,8 +49,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "gamedefs.h" #include "config.h" #include "network.h" -#include "fx_man.h" -#include "music.h" #include "text.h" #include "version.h" #include "network.h" diff --git a/source/sw/src/mfile.h b/source/sw/src/mfile.h index 6ee541090..d8bdb9668 100644 --- a/source/sw/src/mfile.h +++ b/source/sw/src/mfile.h @@ -25,7 +25,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms //------------------------------------------------------------------------- #include "compat.h" -#include "cache1d.h" + #include "savegamehelp.h" BEGIN_SW_NS diff --git a/source/sw/src/miscactr.cpp b/source/sw/src/miscactr.cpp index f6cb36992..0e1e22535 100644 --- a/source/sw/src/miscactr.cpp +++ b/source/sw/src/miscactr.cpp @@ -34,7 +34,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "tags.h" #include "ai.h" #include "quake.h" -#include "fx_man.h" #include "actor.h" #include "sector.h" #include "sprite.h" @@ -168,32 +167,29 @@ int DoToiletGirl(short SpriteNum) { if (RANDOM_RANGE(1000) > 980) { - static int handle; short choose_snd; choose_snd = RANDOM_P2(1024<<4)>>4; - if (!FX_SoundValidAndActive(handle)) + if (!SoundValidAndActive(sp, CHAN_ToiletFart)) { if (choose_snd > 750) - handle = PlaySound(DIGI_TOILETGIRLFART1,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_TOILETGIRLFART1, sp, v3df_dontpan, CHAN_ToiletFart); else if (choose_snd > 350) - handle = PlaySound(DIGI_TOILETGIRLFART2,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_TOILETGIRLFART2, sp, v3df_dontpan, CHAN_ToiletFart); else - handle = PlaySound(DIGI_TOILETGIRLFART3,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_TOILETGIRLFART3, sp, v3df_dontpan, CHAN_ToiletFart); } } } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { if (RANDOM_RANGE(1000<<8)>>8 > 500) - madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_ANIMEMAD2,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_ToiletGirlUzi); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -233,14 +229,12 @@ int NullToiletGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { if (RANDOM_RANGE(1000<<8)>>8 > 500) - madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_ANIMEMAD2,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_ToiletGirlUzi); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -406,7 +400,6 @@ int DoWashGirl(short SpriteNum) USERp u = User[SpriteNum]; SPRITEp sp = User[SpriteNum]->SpriteP; short rnd_range = 0; - static int handle=0; SWBOOL ICanSee = FALSE; DoActorPickClosePlayer(SpriteNum); @@ -414,14 +407,12 @@ int DoWashGirl(short SpriteNum) if (RANDOM_RANGE(1000) > 980 && u->ShellNum <= 0) { - static int handle; - - if (!FX_SoundValidAndActive(handle)) + if (!SoundValidAndActive(sp, CHAN_AnimeSing)) { if (RANDOM_P2(1024<<4)>>4 > 500) - handle = PlaySound(DIGI_ANIMESING1,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMESING1, sp, v3df_dontpan, CHAN_AnimeSing); else - handle = PlaySound(DIGI_ANIMESING2,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMESING2, sp, v3df_dontpan, CHAN_AnimeSing); } ChangeState(SpriteNum,s_WashGirlStandScrub); @@ -444,14 +435,12 @@ int DoWashGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { if (RANDOM_RANGE(1000<<8)>>8 > 500) - madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_ANIMEMAD2,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_WashGirlUzi); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -488,14 +477,12 @@ int NullWashGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { if (RANDOM_RANGE(1000<<8)>>8 > 500) - madhandle = PlaySound(DIGI_ANIMEMAD1,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMEMAD1, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_ANIMEMAD2,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_ANIMEMAD2, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_WashGirlUzi); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -748,7 +735,7 @@ int PachinkoLightOperate(short SpriteNum) // PACHINKO MACHINE #1 //////////////////////////////////////////////////////////////////// -SWBOOL Pachinko_Win_Cheat = FALSE; +CVAR(Bool, Pachinko_Win_Cheat, false, 0) ATTRIBUTE Pachinko1Attrib = { @@ -857,7 +844,7 @@ int PachinkoCheckWin(short SpriteNum) } ActorCoughItem(SpriteNum); // I WON! I WON! - PlaySound(DIGI_PALARM,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_PALARM, sp, v3df_none); // Can't win any more now! SET_BOOL1(sp); @@ -883,13 +870,13 @@ int PachinkoCheckWin(short SpriteNum) //{ //if(rnd > 950) - // PlayerSound(DIGI_SHISEISI,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + // PlayerSound(DIGI_SHISEISI, pp, v3df_follow|v3df_dontpan,pp); //else //if(rnd > 900) - // PlayerSound(DIGI_YOULOOKSTUPID,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + // PlayerSound(DIGI_YOULOOKSTUPID, pp, v3df_follow|v3df_dontpan,pp); //else //if(rnd > 850) - // PlayerSound(DIGI_HURTBAD5,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + // PlayerSound(DIGI_HURTBAD5, pp, v3df_follow|v3df_dontpan,pp); //} return 0; @@ -907,11 +894,11 @@ int Pachinko1Operate(short SpriteNum) { rnd = RANDOM_RANGE(1000); // TEMP SOUNDS: Need pachinko sounds! if (rnd > 700) - PlaySound(DIGI_PROLL1,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_PROLL1, sp, v3df_none); else if (rnd > 400) - PlaySound(DIGI_PROLL2,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_PROLL2, sp, v3df_none); else - PlaySound(DIGI_PROLL3,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_PROLL3, sp, v3df_none); } return 0; @@ -1303,21 +1290,19 @@ int DoCarGirl(short SpriteNum) { if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI049,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI049, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI051,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI051, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI052,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI052, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI054,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI054, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_CarGirlUzi); u->WaitTics = SEC(3)+SEC(RANDOM_RANGE(2<<8)>>8); @@ -1358,21 +1343,19 @@ int NullCarGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI049,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI049, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI051,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI051, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI052,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI052, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI054,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI054, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_CarGirlUzi); u->WaitTics = SEC(3)+SEC(RANDOM_RANGE(2<<8)>>8); @@ -1530,21 +1513,19 @@ int DoMechanicGirl(short SpriteNum) { if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI073,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI073, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI075,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI075, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI077,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI077, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI079,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI079, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_MechanicGirlDrill); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(2<<8)>>8); @@ -1585,21 +1566,19 @@ int NullMechanicGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI073,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI073, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI075,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI075, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI077,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI077, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI079,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI079, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_MechanicGirlDrill); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(2<<8)>>8); @@ -1758,9 +1737,7 @@ int DoSailorGirl(short SpriteNum) { if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); @@ -1769,14 +1746,14 @@ int DoSailorGirl(short SpriteNum) { ActorCoughItem(SpriteNum); alreadythrew++; - madhandle = PlaySound(DIGI_LANI060,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI060, sp, v3df_dontpan, CHAN_AnimeMad); } else if (choose > 500) - madhandle = PlaySound(DIGI_LANI063,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI063, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI065,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI065, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI066,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI066, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_SailorGirlThrow); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -1818,9 +1795,7 @@ int NullSailorGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); @@ -1829,14 +1804,14 @@ int NullSailorGirl(short SpriteNum) { ActorCoughItem(SpriteNum); alreadythrew++; - madhandle = PlaySound(DIGI_LANI060,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI060, sp, v3df_dontpan, CHAN_AnimeMad); } else if (choose > 500) - madhandle = PlaySound(DIGI_LANI063,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI063, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI065,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI065, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI066,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI066, sp, v3df_dontpan, CHAN_AnimeMad); } ChangeState(SpriteNum,s_SailorGirlThrow); u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); @@ -1968,7 +1943,6 @@ int DoPruneGirl(short SpriteNum) USERp u = User[SpriteNum]; SPRITEp sp = User[SpriteNum]->SpriteP; short rnd_range = 0; - static int madhandle, coyhandle; SWBOOL ICanSee = FALSE; DoActorPickClosePlayer(SpriteNum); @@ -1978,19 +1952,19 @@ int DoPruneGirl(short SpriteNum) { if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = STD_RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI089,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI089, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI091,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI091, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI093,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI093, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI095,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI095, sp, v3df_dontpan, CHAN_AnimeMad); } u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); u->FlagOwner = 0; @@ -1998,19 +1972,19 @@ int DoPruneGirl(short SpriteNum) } else { - if (!FX_SoundValidAndActive(coyhandle)) + if (!SoundValidAndActive(sp, CHAN_CoyHandle)) { short choose; choose = STD_RANDOM_RANGE(1000); if (choose > 990) - coyhandle = PlaySound(DIGI_PRUNECACKLE,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_PRUNECACKLE, sp, v3df_dontpan, CHAN_CoyHandle); else if (choose > 985) - coyhandle = PlaySound(DIGI_PRUNECACKLE2,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_PRUNECACKLE2, sp, v3df_dontpan, CHAN_CoyHandle); else if (choose > 980) - coyhandle = PlaySound(DIGI_PRUNECACKLE3,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_PRUNECACKLE3, sp, v3df_dontpan, CHAN_CoyHandle); else if (choose > 975) - coyhandle = PlaySound(DIGI_LANI091,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI091, sp, v3df_dontpan, CHAN_CoyHandle); } } @@ -2047,21 +2021,19 @@ int NullPruneGirl(short SpriteNum) } else if ((u->WaitTics -= ACTORMOVETICS) <= 0 && ICanSee) { - static int madhandle; - - if (!FX_SoundValidAndActive(madhandle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { short choose; choose = RANDOM_RANGE(1000); if (choose > 750) - madhandle = PlaySound(DIGI_LANI089,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI089, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 500) - madhandle = PlaySound(DIGI_LANI091,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI091, sp, v3df_dontpan, CHAN_AnimeMad); else if (choose > 250) - madhandle = PlaySound(DIGI_LANI093,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI093, sp, v3df_dontpan, CHAN_AnimeMad); else - madhandle = PlaySound(DIGI_LANI095,&sp->x,&sp->y,&sp->z,v3df_dontpan); + PlaySound(DIGI_LANI095, sp, v3df_dontpan, CHAN_AnimeMad); } u->WaitTics = SEC(1)+SEC(RANDOM_RANGE(3<<8)>>8); u->FlagOwner = 0; diff --git a/source/sw/src/network.cpp b/source/sw/src/network.cpp index d4c5db866..cba519ea4 100644 --- a/source/sw/src/network.cpp +++ b/source/sw/src/network.cpp @@ -1425,7 +1425,7 @@ getpackets(void) break; } - PlaySound(DIGI_PMESSAGE,&tp->posx,&tp->posy,&tp->posz,v3df_dontpan); + PlaySound(DIGI_PMESSAGE,tp,v3df_dontpan); memcpy(ds,&packbuf[3],packbufleng-3); ds[packbufleng-3] = 0; diff --git a/source/sw/src/ninja.cpp b/source/sw/src/ninja.cpp index 7059274c8..22a2938db 100644 --- a/source/sw/src/ninja.cpp +++ b/source/sw/src/ninja.cpp @@ -1965,7 +1965,7 @@ DoNinjaHariKari(short SpriteNum) SET(sp->extra, SPRX_BREAKABLE); SET(sp->cstat, CSTAT_SPRITE_BREAKABLE); - PlaySound(DIGI_NINJAUZIATTACK,&sp->x,&sp->y,&sp->z,v3df_follow); + PlaySound(DIGI_NINJAUZIATTACK, sp, v3df_follow); SpawnBlood(SpriteNum, SpriteNum, -1, -1, -1, -1); @@ -2005,7 +2005,7 @@ DoNinjaGrabThroat(short SpriteNum) sp->xvel = 0; //u->jump_speed = -300; //DoActorBeginJump(SpriteNum); - PlaySound(DIGI_NINJASCREAM,&sp->x,&sp->y,&sp->z,v3df_follow); + PlaySound(DIGI_NINJASCREAM, sp, v3df_follow); } return 0; @@ -2258,7 +2258,6 @@ PlayerDeathReset(PLAYERp pp) pp->Bloody = FALSE; pp->TestNukeInit = FALSE; pp->InitingNuke = FALSE; - pp->nukevochandle = 0; pp->NukeInitialized = FALSE; pp->BunnyMode = FALSE; @@ -2348,7 +2347,6 @@ PlayerGameReset(PLAYERp pp) pp->Bloody = FALSE; pp->TestNukeInit = FALSE; pp->InitingNuke = FALSE; - pp->nukevochandle = 0; pp->NukeInitialized = FALSE; pp->BunnyMode = FALSE; pp->SecretsFound = 0; diff --git a/source/sw/src/panel.cpp b/source/sw/src/panel.cpp index 378896da2..cb1d31e6c 100644 --- a/source/sw/src/panel.cpp +++ b/source/sw/src/panel.cpp @@ -43,9 +43,9 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "player.h" #include "weapon.h" -#include "fx_man.h" #include "menu/menu.h" #include "swcvar.h" +#include "sound/s_soundinternal.h" BEGIN_SW_NS @@ -266,7 +266,7 @@ void DoPlayerChooseYell(PLAYERp pp) choose_snd = STD_RANDOM_RANGE(MAX_YELLSOUNDS); if (pp == Player+myconnectindex) - PlayerSound(PlayerYellVocs[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(PlayerYellVocs[choose_snd], v3df_follow|v3df_dontpan,pp); } void ArmorCalc(int damage_amt, int *armor_damage, int *player_damage) @@ -353,13 +353,11 @@ void PlayerUpdateHealth(PLAYERp pp, short value) if (u->Health > 50) { - PlayerSound(PlayerPainVocs[choosesnd],&pp->posx, - &pp->posy,&pp->posy,v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(PlayerPainVocs[choosesnd],v3df_dontpan|v3df_doppler|v3df_follow,pp); } else { - PlayerSound(PlayerLowHealthPainVocs[choosesnd],&pp->posx, - &pp->posy,&pp->posy,v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(PlayerLowHealthPainVocs[choosesnd],v3df_dontpan|v3df_doppler|v3df_follow,pp); } } @@ -884,7 +882,7 @@ int WeaponOperate(PLAYERp pp) if (TEST(pp->Flags, PF_TWO_UZI)) { pp->WpnUziType++; - PlaySound(DIGI_UZI_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_UZI_UP, pp, v3df_follow); if (pp->WpnUziType > 1) pp->WpnUziType = 0; } @@ -897,7 +895,7 @@ int WeaponOperate(PLAYERp pp) if (u->WeaponNum == WPN_MICRO) { pp->WpnRocketType++; - PlaySound(DIGI_ROCKET_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_ROCKET_UP, pp, v3df_follow); if (pp->WpnRocketType > 2) pp->WpnRocketType = 0; if (pp->WpnRocketType == 2 && pp->WpnRocketNuke == 0) @@ -915,7 +913,7 @@ int WeaponOperate(PLAYERp pp) pp->WpnShotgunType++; if (pp->WpnShotgunType > 1) pp->WpnShotgunType = 0; - PlaySound(DIGI_SHOTGUN_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_SHOTGUN_UP, pp, v3df_follow); } InitWeaponShotgun(pp); break; @@ -930,7 +928,7 @@ int WeaponOperate(PLAYERp pp) pp->WpnRailType = 0; } if (pp->WpnRailType == 1) - PlaySound(DIGI_RAIL_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_RAIL_UP, pp, v3df_follow); #endif InitWeaponRail(pp); } @@ -951,7 +949,7 @@ int WeaponOperate(PLAYERp pp) pp->WpnFlameType = 0; // if(pp->Wpn[WPN_HOTHEAD]) pHotHeadOverlays(pp->Wpn[WPN_HOTHEAD], pp->WpnFlameType); - PlaySound(DIGI_HOTHEADSWITCH, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow); + PlaySound(DIGI_HOTHEADSWITCH, pp, v3df_dontpan|v3df_follow); } InitWeaponHothead(pp); @@ -998,11 +996,7 @@ int WeaponOperate(PLAYERp pp) if (pp->WpnRocketType != 2 || pp->CurWpn != pp->Wpn[WPN_MICRO]) { pp->InitingNuke = FALSE; - if (pp->nukevochandle > 0) - { - FX_StopSound(pp->nukevochandle); - pp->nukevochandle = 0; - } + soundEngine->StopSound(SOURCE_Player, pp, CHAN_WEAPON); } return 0; @@ -1349,19 +1343,19 @@ InitWeaponSword(PLAYERp pp) psp->RestState = ps_SwordRest; pSetState(psp, psp->PresentState); - PlaySound(DIGI_SWORD_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_SWORD_UP, pp, v3df_follow|v3df_dontpan); if (pp == Player+myconnectindex) { rnd_num = STD_RANDOM_RANGE(1024); if (rnd_num > 900) - PlaySound(DIGI_TAUNTAI2, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_TAUNTAI2, pp, v3df_follow|v3df_dontpan); else if (rnd_num > 800) - PlaySound(DIGI_PLAYERYELL1, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_PLAYERYELL1, pp, v3df_follow|v3df_dontpan); else if (rnd_num > 700) - PlaySound(DIGI_PLAYERYELL2, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_PLAYERYELL2, pp, v3df_follow|v3df_dontpan); else if (rnd_num > 600) - PlayerSound(DIGI_ILIKESWORD,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_ILIKESWORD, v3df_follow|v3df_dontpan,pp); } FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); @@ -1820,11 +1814,11 @@ InitWeaponStar(PLAYERp pp) //psp->RestState = ps_ThrowStar; pSetState(psp, psp->PresentState); - PlaySound(DIGI_PULL, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_PULL, pp, v3df_follow|v3df_dontpan); if (STD_RANDOM_RANGE(1000) > 900 && pp == Player+myconnectindex) { if (!sw_darts) - PlayerSound(DIGI_ILIKESHURIKEN,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_ILIKESHURIKEN, v3df_follow|v3df_dontpan,pp); } FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); @@ -2196,8 +2190,7 @@ pSpawnUziClip(PANEL_SPRITEp gun) { PANEL_SPRITEp New; - PlaySound(DIGI_REMOVECLIP, &gun->PlayerP->posx, &gun->PlayerP->posy, - &gun->PlayerP->posz,v3df_follow|v3df_dontpan|v3df_doppler|v3df_follow); + PlaySound(DIGI_REMOVECLIP, gun->PlayerP,v3df_follow|v3df_dontpan|v3df_doppler|v3df_follow); if (TEST(gun->flags, PANF_XFLIP)) { @@ -2279,8 +2272,7 @@ pUziReload(PANEL_SPRITEp nclip) { if (nclip->x < gun->x) { - PlaySound(DIGI_REPLACECLIP, &nclip->PlayerP->posx, &nclip->PlayerP->posy, - &nclip->PlayerP->posz,v3df_follow|v3df_dontpan|v3df_doppler); + PlaySound(DIGI_REPLACECLIP, nclip->PlayerP,v3df_follow|v3df_dontpan|v3df_doppler); nclip->x = gun->x - UZI_CLIP_XOFF; nclip->y = gun->y + UZI_CLIP_YOFF; @@ -2294,8 +2286,7 @@ pUziReload(PANEL_SPRITEp nclip) { if (nclip->x > gun->x) { - PlaySound(DIGI_REPLACECLIP, &nclip->PlayerP->posx, &nclip->PlayerP->posy, - &nclip->PlayerP->posz,v3df_follow|v3df_dontpan|v3df_doppler); + PlaySound(DIGI_REPLACECLIP, nclip->PlayerP,v3df_follow|v3df_dontpan|v3df_doppler); nclip->x = gun->x + UZI_CLIP_XOFF; nclip->y = gun->y + UZI_CLIP_YOFF; @@ -2523,7 +2514,7 @@ InitWeaponUzi(PLAYERp pp) InitWeaponUzi2(psp); } - PlaySound(DIGI_UZI_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_UZI_UP, pp, v3df_follow); FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); FLAG_KEY_RESET(psp->PlayerP, SK_SHOOT); @@ -3231,7 +3222,7 @@ InitWeaponShotgun(PLAYERp pp) psp->RestState = ps_ShotgunRest; pSetState(psp, psp->PresentState); - PlaySound(DIGI_SHOTGUN_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_SHOTGUN_UP, pp, v3df_follow); FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); FLAG_KEY_RESET(psp->PlayerP, SK_SHOOT); @@ -3315,8 +3306,7 @@ pShotgunReloadDown(PANEL_SPRITEp psp) if (psp->y >= SHOTGUN_YOFF + (tilesiz[picnum].y/2)) { - PlaySound(DIGI_ROCKET_UP, &psp->PlayerP->posx, &psp->PlayerP->posy, - &psp->PlayerP->posz,v3df_follow|v3df_dontpan|v3df_doppler); + PlaySound(DIGI_ROCKET_UP, psp->PlayerP,v3df_follow|v3df_dontpan|v3df_doppler); psp->y = SHOTGUN_YOFF + (tilesiz[picnum].y/2); @@ -3333,8 +3323,7 @@ pShotgunReloadUp(PANEL_SPRITEp psp) if (psp->y < SHOTGUN_YOFF) { - PlaySound(DIGI_SHOTGUN_UP, &psp->PlayerP->posx, &psp->PlayerP->posy, - &psp->PlayerP->posz,v3df_follow|v3df_dontpan|v3df_doppler); + PlaySound(DIGI_SHOTGUN_UP, psp->PlayerP,v3df_follow|v3df_dontpan|v3df_doppler); psp->y = SHOTGUN_YOFF; @@ -3701,8 +3690,6 @@ PANEL_STATE ps_RetractRail[] = //#define RAIL_XOFF (160+60) #define RAIL_XOFF (160+6) -static int railvochandle=0; - void InitWeaponRail(PLAYERp pp) { @@ -3746,8 +3733,8 @@ InitWeaponRail(PLAYERp pp) psp->RestState = ps_RailRest; pSetState(psp, psp->PresentState); - PlaySound(DIGI_RAIL_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); - railvochandle = PlaySound(DIGI_RAILREADY, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_RAIL_UP, pp, v3df_follow); + PlaySound(DIGI_RAILREADY, pp, v3df_follow|v3df_dontpan); Set3DSoundOwner(psp->PlayerP->PlayerSprite); FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); @@ -4206,7 +4193,7 @@ InitWeaponHothead(PLAYERp pp) psp->over[0].xoff = HOTHEAD_FINGER_XOFF; psp->over[0].yoff = HOTHEAD_FINGER_YOFF; - PlaySound(DIGI_GRDALERT, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_GRDALERT, pp, v3df_follow|v3df_dontpan); } void @@ -4649,7 +4636,7 @@ InitWeaponMicro(PLAYERp pp) if (pp->WpnRocketType == 2 && !pp->InitingNuke && !pp->NukeInitialized) pp->TestNukeInit = pp->InitingNuke = TRUE; - PlaySound(DIGI_ROCKET_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_ROCKET_UP, pp, v3df_follow); FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); FLAG_KEY_RESET(psp->PlayerP, SK_SHOOT); @@ -4892,11 +4879,9 @@ pMicroRest(PANEL_SPRITEp psp) { choose_voc = STD_RANDOM_RANGE(1024); if (choose_voc > 600) - PlayerSound(DIGI_TAUNTAI2,&psp->PlayerP->posx, - &psp->PlayerP->posy,&psp->PlayerP->posy,v3df_dontpan|v3df_follow,psp->PlayerP); + PlayerSound(DIGI_TAUNTAI2,v3df_dontpan|v3df_follow,psp->PlayerP); else if (choose_voc > 300) - PlayerSound(DIGI_TAUNTAI4,&psp->PlayerP->posx, - &psp->PlayerP->posy,&psp->PlayerP->posy,v3df_dontpan|v3df_follow,psp->PlayerP); + PlayerSound(DIGI_TAUNTAI4,v3df_dontpan|v3df_follow,psp->PlayerP); } } @@ -4969,7 +4954,7 @@ pMicroFire(PANEL_SPRITEp psp) InitRocket(psp->PlayerP); break; case 2: - PlaySound(DIGI_WARNING,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_dontpan|v3df_follow); + PlaySound(DIGI_WARNING,psp->PlayerP,v3df_dontpan|v3df_follow); InitNuke(psp->PlayerP); psp->PlayerP->NukeInitialized = FALSE; break; @@ -5016,8 +5001,7 @@ pMicroStandBy(PANEL_SPRITEp psp) PLAYERp pp = psp->PlayerP; pMicroOverlays(psp); - pp->nukevochandle = - PlaySound(DIGI_NUKESTDBY, &psp->PlayerP->posx, &psp->PlayerP->posy, &psp->PlayerP->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_NUKESTDBY, pp, v3df_follow|v3df_dontpan, CHAN_WEAPON); } void @@ -5025,8 +5009,7 @@ pMicroCount(PANEL_SPRITEp psp) { PLAYERp pp = psp->PlayerP; - pp->nukevochandle = - PlaySound(DIGI_NUKECDOWN, &psp->PlayerP->posx, &psp->PlayerP->posy, &psp->PlayerP->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_NUKECDOWN, pp, v3df_follow|v3df_dontpan, CHAN_WEAPON); } void @@ -5034,8 +5017,7 @@ pMicroReady(PANEL_SPRITEp psp) { PLAYERp pp = psp->PlayerP; - pp->nukevochandle = - PlaySound(DIGI_NUKEREADY, &psp->PlayerP->posx, &psp->PlayerP->posy, &psp->PlayerP->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_NUKEREADY, pp, v3df_follow|v3df_dontpan, CHAN_WEAPON); pp->NukeInitialized = TRUE; } @@ -5136,7 +5118,7 @@ InitWeaponHeart(PLAYERp pp) pp->WpnUziType = 2; // Make uzi's go away! RetractCurWpn(pp); - PlaySound(DIGI_HEARTBEAT, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan|v3df_doppler); + PlaySound(DIGI_HEARTBEAT, pp, v3df_follow|v3df_dontpan|v3df_doppler); // Set up the new Weapon variables psp = pp->CurWpn = pp->Wpn[WPN_HEART]; @@ -5281,9 +5263,9 @@ pHeartAttack(PANEL_SPRITEp psp) //int InitHeartAttack(PLAYERp pp); // CTW MODIFICATION END - PlaySound(DIGI_HEARTFIRE,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan); + PlaySound(DIGI_HEARTFIRE, pp, v3df_follow|v3df_dontpan); if (RANDOM_RANGE(1000) > 800) - PlayerSound(DIGI_JG9009,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_JG9009, v3df_follow|v3df_dontpan,pp); InitHeartAttack(psp->PlayerP); } @@ -5400,7 +5382,7 @@ SpawnSmallHeartBlood(PANEL_SPRITEp psp) {0, 0, 0, 0, 0, 0, 0, {0,0}}, }; - PlaySound(DIGI_HEARTBEAT, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan|v3df_doppler); + PlaySound(DIGI_HEARTBEAT, pp, v3df_follow|v3df_dontpan|v3df_doppler); for (hsp = HeartShrap; hsp->lo_jump_speed; hsp++) { @@ -5645,7 +5627,7 @@ InitWeaponGrenade(PLAYERp pp) pGrenadePresentSetup(psp); - PlaySound(DIGI_GRENADE_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_GRENADE_UP, pp, v3df_follow); FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); FLAG_KEY_RESET(psp->PlayerP, SK_SHOOT); @@ -5931,7 +5913,7 @@ InitWeaponMine(PLAYERp pp) psp->RestState = ps_MineRest; pSetState(psp, psp->PresentState); - PlaySound(DIGI_PULL, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_PULL, pp, v3df_follow|v3df_dontpan); FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); FLAG_KEY_RESET(psp->PlayerP, SK_SHOOT); @@ -5942,7 +5924,7 @@ pMineUpSound(PANEL_SPRITEp psp) { PLAYERp pp = psp->PlayerP; - PlaySound(DIGI_MINE_UP, &pp->posx, &pp->posy, &pp->posz, v3df_follow); + PlaySound(DIGI_MINE_UP, pp, v3df_follow); } void @@ -6191,10 +6173,10 @@ InitChops(PLAYERp pp) psp->RetractState = ps_ChopsRetract; psp->RestState = ps_ChopsAttack1; - PlaySound(DIGI_BUZZZ,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_none); + PlaySound(DIGI_BUZZZ, psp->PlayerP,v3df_none); if (RANDOM_RANGE(1000) > 750) - PlayerSound(DIGI_MRFLY,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_follow|v3df_dontpan,psp->PlayerP); + PlayerSound(DIGI_MRFLY,v3df_follow|v3df_dontpan,psp->PlayerP); } @@ -6202,15 +6184,15 @@ void pChopsClick(PANEL_SPRITEp psp) { int16_t rnd_rng; - PlaySound(DIGI_CHOP_CLICK,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_none); + PlaySound(DIGI_CHOP_CLICK,psp->PlayerP,v3df_none); rnd_rng = RANDOM_RANGE(1000); if (rnd_rng > 950) - PlayerSound(DIGI_SEARCHWALL,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_follow|v3df_dontpan,psp->PlayerP); + PlayerSound(DIGI_SEARCHWALL,v3df_follow|v3df_dontpan,psp->PlayerP); else if (rnd_rng > 900) - PlayerSound(DIGI_EVADEFOREVER,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_follow|v3df_dontpan,psp->PlayerP); + PlayerSound(DIGI_EVADEFOREVER,v3df_follow|v3df_dontpan,psp->PlayerP); else if (rnd_rng > 800) - PlayerSound(DIGI_SHISEISI,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_follow|v3df_dontpan,psp->PlayerP); + PlayerSound(DIGI_SHISEISI,v3df_follow|v3df_dontpan,psp->PlayerP); } void @@ -6273,7 +6255,7 @@ pChopsWait(PANEL_SPRITEp psp) // do a random attack here psp->x = CHOPS_XOFF + (RANDOM_P2(128) - 64); - PlaySound(DIGI_BUZZZ,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_none); + PlaySound(DIGI_BUZZZ,psp->PlayerP,v3df_none); pSetState(psp, psp_ChopsAttack[RANDOM_RANGE(SIZ(psp_ChopsAttack))]); } } @@ -6296,7 +6278,7 @@ pChopsRetract(PANEL_SPRITEp psp) if (psp->y >= CHOPS_YOFF + tilesiz[picnum].y) { if (RANDOM_RANGE(1000) > 800) - PlayerSound(DIGI_GETTINGSTIFF,&psp->PlayerP->posx,&psp->PlayerP->posy,&psp->PlayerP->posz,v3df_follow|v3df_dontpan,psp->PlayerP); + PlayerSound(DIGI_GETTINGSTIFF,v3df_follow|v3df_dontpan,psp->PlayerP); psp->PlayerP->Chops = NULL; pKillSprite(psp); } @@ -6604,11 +6586,11 @@ InitWeaponFist(PLAYERp pp) rnd_num = RANDOM_P2(1024); if (rnd_num > 900) - PlaySound(DIGI_TAUNTAI2, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_TAUNTAI2, pp, v3df_follow|v3df_dontpan); else if (rnd_num > 800) - PlaySound(DIGI_PLAYERYELL1, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_PLAYERYELL1, pp, v3df_follow|v3df_dontpan); else if (rnd_num > 700) - PlaySound(DIGI_PLAYERYELL2, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); + PlaySound(DIGI_PLAYERYELL2, pp, v3df_follow|v3df_dontpan); FLAG_KEY_RELEASE(psp->PlayerP, SK_SHOOT); FLAG_KEY_RESET(psp->PlayerP, SK_SHOOT); diff --git a/source/sw/src/player.cpp b/source/sw/src/player.cpp index f320a223a..02d4d3940 100644 --- a/source/sw/src/player.cpp +++ b/source/sw/src/player.cpp @@ -42,7 +42,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "common_game.h" #include "gamecontrol.h" -#include "control.h" #include "trigger.h" #include "savedef.h" @@ -51,7 +50,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "pal.h" #include "demo.h" #include "mclip.h" -#include "fx_man.h" #include "sprite.h" #include "weapon.h" @@ -61,12 +59,12 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "sector.h" #include "actor.h" #include "colormap.h" -#include "music.h" #include "vis.h" #include "track.h" #include "interp.h" #include "menu/menu.h" #include "gstrings.h" +#include "z_music.h" BEGIN_SW_NS @@ -1457,7 +1455,7 @@ DoPlayerWarpTeleporter(PLAYERp pp) default: DoPlayerTeleportToSprite(pp, sp_warp); - PlaySound(DIGI_TELEPORT, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_TELEPORT, pp, v3df_none); DoPlayerResetMovement(pp); @@ -3638,7 +3636,7 @@ void StackedWaterSplash(PLAYERp pp) if (sectnum >= 0 && SectorIsUnderwaterArea(sectnum)) { - PlaySound(DIGI_SPLASH1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + PlaySound(DIGI_SPLASH1, pp, v3df_dontpan); } } } @@ -3649,7 +3647,6 @@ DoPlayerFall(PLAYERp pp) short i; int recoil_amt; int depth; - static int handle=0; // reset flag key for double jumps if (!TEST_SYNC_KEY(pp, SK_JUMP)) @@ -3679,9 +3676,7 @@ DoPlayerFall(PLAYERp pp) if (pp->jump_speed > 2000) { - PlayerSound(DIGI_FALLSCREAM, &pp->posx, &pp->posy, &pp->posz, - v3df_dontpan|v3df_doppler|v3df_follow,pp); - handle = pp->TalkVocHandle; // Save id for later + PlayerSound(DIGI_FALLSCREAM, v3df_dontpan|v3df_doppler|v3df_follow,pp); } else if (pp->jump_speed > 1300) { @@ -3722,22 +3717,13 @@ DoPlayerFall(PLAYERp pp) if (sectu && (TEST(sectp->extra, SECTFX_LIQUID_MASK) != SECTFX_LIQUID_NONE)) { - PlaySound(DIGI_SPLASH1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + PlaySound(DIGI_SPLASH1, pp, v3df_dontpan); } else { if (pp->jump_speed > 1020) // Feet hitting ground sound - PlaySound(DIGI_HITGROUND, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan); - } - - if (FX_SoundValidAndActive(handle)) - { - // My sound code will detect the sound has stopped and clean up - // for you. - FX_StopSound(handle); - pp->PlayerTalking = FALSE; - handle = 0; + PlaySound(DIGI_HITGROUND, pp, v3df_follow|v3df_dontpan); } // i any kind of crawl key get rid of recoil @@ -3760,7 +3746,7 @@ DoPlayerFall(PLAYERp pp) if (pp->jump_speed > 1700 && depth == 0) { - PlayerSound(DIGI_PLAYERPAIN2, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_PLAYERPAIN2, v3df_follow|v3df_dontpan,pp); // PlayerUpdateHealth(pp, -RANDOM_RANGE(PLAYER_FALL_DAMAGE_AMOUNT) - 2); if (pp->jump_speed > 1700 && pp->jump_speed < 4000) @@ -4698,7 +4684,7 @@ PlayerCanDiveNoWarp(PLAYERp pp) pp->z_speed = Z(20); pp->jump_speed = 0; - PlaySound(DIGI_SPLASH1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + PlaySound(DIGI_SPLASH1, pp, v3df_dontpan); DoPlayerBeginDiveNoWarp(pp); return TRUE; } @@ -5161,15 +5147,10 @@ DoPlayerStopDiveNoWarp(PLAYERp pp) if (!NoMeters) SetRedrawScreen(pp); - if (FX_SoundValidAndActive(pp->TalkVocHandle)) - { - FX_StopSound(pp->TalkVocHandle); - pp->TalkVocHandle = 0; - pp->PlayerTalking = FALSE; - } + StopPlayerSound(pp); // stop diving no warp - PlayerSound(DIGI_SURFACE,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow|v3df_doppler,pp); + PlayerSound(DIGI_SURFACE, v3df_dontpan|v3df_follow|v3df_doppler,pp); pp->bob_amt = 0; @@ -5197,15 +5178,10 @@ DoPlayerStopDive(PLAYERp pp) if (!NoMeters) SetRedrawScreen(pp); - if (FX_SoundValidAndActive(pp->TalkVocHandle)) - { - FX_StopSound(pp->TalkVocHandle); - pp->TalkVocHandle = 0; - pp->PlayerTalking = FALSE; - } + StopPlayerSound(pp); // stop diving with warp - PlayerSound(DIGI_SURFACE,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow|v3df_doppler,pp); + PlayerSound(DIGI_SURFACE, v3df_dontpan|v3df_follow|v3df_doppler,pp); pp->bob_amt = 0; DoPlayerWarpToSurface(pp); @@ -5290,7 +5266,7 @@ DoPlayerDive(PLAYERp pp) { pp->DiveDamageTics = PLAYER_DIVE_DAMAGE_TIME; //PlayerUpdateHealth(pp, PLAYER_DIVE_DAMAGE_AMOUNT); - PlayerSound(DIGI_WANGDROWNING, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow, pp); + PlayerSound(DIGI_WANGDROWNING, v3df_dontpan|v3df_follow, pp); PlayerUpdateHealth(pp, -3 -(RANDOM_RANGE(7<<8)>>8)); PlayerCheckDeath(pp, -1); if (TEST(pp->Flags, PF_DEAD)) @@ -5429,7 +5405,7 @@ DoPlayerDive(PLAYERp pp) // Random bubble sounds // if((RANDOM_RANGE(1000<<5)>>5) < 100) - // PlaySound(DIGI_BUBBLES, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow); + // PlaySound(DIGI_BUBBLES, pp, v3df_dontpan|v3df_follow); if ((!Prediction && pp->z_speed && ((RANDOM_P2(1024<<5)>>5) < 64)) || (PLAYER_MOVING(pp) && (RANDOM_P2(1024<<5)>>5) < 64)) @@ -5439,7 +5415,7 @@ DoPlayerDive(PLAYERp pp) SPRITEp bp; int nx,ny; - PlaySound(DIGI_BUBBLES, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_BUBBLES, pp, v3df_none); bubble = SpawnBubble(pp->SpriteP - sprite); if (bubble >= 0) { @@ -5893,7 +5869,7 @@ DoPlayerBeginOperate(PLAYERp pp) } else { - PlayerSound(DIGI_USEBROKENVEHICLE, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_USEBROKENVEHICLE, v3df_follow|v3df_dontpan,pp); return; } } @@ -5981,7 +5957,7 @@ DoPlayerBeginRemoteOperate(PLAYERp pp, SECTOR_OBJECTp sop) } else { - PlayerSound(DIGI_USEBROKENVEHICLE, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_USEBROKENVEHICLE, v3df_follow|v3df_dontpan,pp); return; } } @@ -6334,9 +6310,9 @@ DoPlayerDeathFall(PLAYERp pp) SpawnSplash(pp->PlayerSprite); if (RANDOM_RANGE(1000) > 500) - PlaySound(DIGI_BODYFALL1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + PlaySound(DIGI_BODYFALL1, pp, v3df_dontpan); else - PlaySound(DIGI_BODYFALL2, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + PlaySound(DIGI_BODYFALL2, pp, v3df_dontpan); pp->posz = loz - PLAYER_DEATH_HEIGHT; RESET(pp->Flags, PF_FALLING); @@ -6496,21 +6472,12 @@ DoPlayerBeginDie(PLAYERp pp) if (GodMode) return; - // Override any previous talking, death scream has precedance - if (pp->PlayerTalking) - { - if (FX_SoundValidAndActive(pp->TalkVocHandle)) - FX_StopSound(pp->TalkVocHandle); - pp->PlayerTalking = FALSE; - pp->TalkVocnum = -1; - pp->TalkVocHandle = -1; - } + StopPlayerSound(pp); // Do the death scream choosesnd = RANDOM_RANGE(MAX_PAIN); - PlayerSound(PlayerLowHealthPainVocs[choosesnd],&pp->posx, - &pp->posy,&pp->posy,v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(PlayerLowHealthPainVocs[choosesnd],v3df_dontpan|v3df_doppler|v3df_follow,pp); #if 0 if (!CommEnabled && numplayers <= 1 && QuickLoadNum >= 0) @@ -6640,7 +6607,7 @@ DoPlayerBeginDie(PLAYERp pp) case PLAYER_DEATH_FLIP: case PLAYER_DEATH_RIPPER: - //PlaySound(DIGI_SCREAM1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow); + //PlaySound(DIGI_SCREAM1, pp, v3df_dontpan|v3df_follow); SET(pp->Flags, PF_JUMPING); u->ID = NINJA_DEAD; @@ -6658,7 +6625,7 @@ DoPlayerBeginDie(PLAYERp pp) break; case PLAYER_DEATH_CRUMBLE: - PlaySound(DIGI_BODYSQUISH1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + PlaySound(DIGI_BODYSQUISH1, pp, v3df_dontpan); SET(pp->Flags, PF_DEAD_HEAD | PF_JUMPING); pp->jump_speed = -300; @@ -6674,7 +6641,7 @@ DoPlayerBeginDie(PLAYERp pp) break; case PLAYER_DEATH_EXPLODE: - PlaySound(DIGI_BODYSQUISH1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + PlaySound(DIGI_BODYSQUISH1, pp, v3df_dontpan); SET(pp->Flags, PF_DEAD_HEAD | PF_JUMPING); pp->jump_speed = -650; @@ -6691,7 +6658,7 @@ DoPlayerBeginDie(PLAYERp pp) break; case PLAYER_DEATH_SQUISH: - PlaySound(DIGI_BODYCRUSHED1, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + PlaySound(DIGI_BODYCRUSHED1, pp, v3df_dontpan); SET(pp->Flags, PF_DEAD_HEAD | PF_JUMPING); pp->jump_speed = 200; @@ -6791,7 +6758,7 @@ void DoPlayerDeathHurl(PLAYERp pp) { SpawnShrap(pp->PlayerSprite, -1); if (RANDOM_RANGE(1000) > 400) - PlayerSound(DIGI_DHVOMIT, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_DHVOMIT, v3df_dontpan|v3df_follow,pp); } return; } @@ -6876,7 +6843,7 @@ void DoPlayerDeathCheckKeys(PLAYERp pp) pp->SpriteP->ang = pp->pang; DoSpawnTeleporterEffect(pp->SpriteP); - PlaySound(DIGI_TELEPORT, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_TELEPORT, pp, v3df_none); DoPlayerZrange(pp); @@ -7028,7 +6995,7 @@ void DoPlayerDeathMoveHead(PLAYERp pp) short hit_sprite = -2; SPRITEp hsp; - //PlaySound(DIGI_DHCLUNK, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + //PlaySound(DIGI_DHCLUNK, pp, v3df_dontpan); hit_sprite = NORM_SPRITE(u->ret); hsp = &sprite[hit_sprite]; @@ -7048,7 +7015,7 @@ void DoPlayerDeathMoveHead(PLAYERp pp) { short w,nw,wall_ang,dang; - //PlaySound(DIGI_DHCLUNK, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan); + //PlaySound(DIGI_DHCLUNK, pp, v3df_dontpan); w = NORM_WALL(u->ret); @@ -7889,14 +7856,14 @@ void PauseMultiPlay(void) SavePrediction = PredictionOn; PredictionOn = FALSE; - MUSIC_Pause(); + Mus_SetPaused(true); } else { PredictionOn = SavePrediction; - MUSIC_Continue(); TRAVERSE_CONNECT(p) pClearTextLine(Player + p, 100); + Mus_SetPaused(false); } } } @@ -8101,8 +8068,8 @@ domovethings(void) MultiPlayLimits(); - if (MoveSkip8 == 0) // 8=5x 4=10x, 2=20x, 0=40x per second - DoUpdateSounds3D(); + //if (MoveSkip8 == 0) // 8=5x 4=10x, 2=20x, 0=40x per second + DoUpdateSounds(); CorrectPrediction(movefifoplc - 1); diff --git a/source/sw/src/predict.cpp b/source/sw/src/predict.cpp index 3d4481ab0..0b2865cbf 100644 --- a/source/sw/src/predict.cpp +++ b/source/sw/src/predict.cpp @@ -33,14 +33,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "names2.h" #include "panel.h" #include "game.h" -//#include "quake.h" -//#include "jsector.h" - -//#include "mytypes.h" -//#include "control.h" -//#include "gamecontrol.h" #include "network.h" -//#include "symutil.h" BEGIN_SW_NS diff --git a/source/sw/src/quake.cpp b/source/sw/src/quake.cpp index 2e4ce0dcd..0c9533b48 100644 --- a/source/sw/src/quake.cpp +++ b/source/sw/src/quake.cpp @@ -273,7 +273,7 @@ int SpawnQuake(short sectnum, int x, int y, int z, QUAKE_AngAmt(sp) = 8; QUAKE_PosAmt(sp) = 0; - PlaySound(DIGI_ERUPTION, &sp->x, &sp->y, &sp->z, v3df_follow|v3df_dontpan); + PlaySound(DIGI_ERUPTION, sp, v3df_follow|v3df_dontpan); Set3DSoundOwner(SpriteNum); return SpriteNum; diff --git a/source/sw/src/ripper2.cpp b/source/sw/src/ripper2.cpp index e8a961a16..3a139c67a 100644 --- a/source/sw/src/ripper2.cpp +++ b/source/sw/src/ripper2.cpp @@ -36,7 +36,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "actor.h" #include "sprite.h" #include "track.h" -#include "fx_man.h" BEGIN_SW_NS @@ -1246,12 +1245,11 @@ int DoRipper2StandHeart(short SpriteNum) { SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; - static int riphearthandle; NullRipper2(SpriteNum); - if (!FX_SoundValidAndActive(riphearthandle)) - riphearthandle = PlaySound(DIGI_RIPPER2HEARTOUT,&sp->x,&sp->y,&sp->z,v3df_none); + if (!SoundValidAndActive(sp, CHAN_RipHeart)) + PlaySound(DIGI_RIPPER2HEARTOUT, sp, v3df_none, CHAN_RipHeart); if ((u->WaitTics -= ACTORMOVETICS) <= 0) NewStateGroup(SpriteNum, sg_Ripper2Run); @@ -1375,7 +1373,7 @@ int ChestRipper2(short SpriteNum) { SPRITEp sp = &sprite[SpriteNum]; - PlaySound(DIGI_RIPPER2CHEST,&sp->x,&sp->y,&sp->z,v3df_follow); + PlaySound(DIGI_RIPPER2CHEST, sp, v3df_follow); return 0; } diff --git a/source/sw/src/save.cpp b/source/sw/src/save.cpp index d4ec3501f..2faa576e6 100644 --- a/source/sw/src/save.cpp +++ b/source/sw/src/save.cpp @@ -48,9 +48,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms //#define FILE_TYPE 1 #include "mfile.h" -#include "fx_man.h" -#include "music.h" - #include "weapon.h" #include "cache.h" #include "colormap.h" @@ -403,6 +400,7 @@ bool GameInterface::SaveGame(FSaveGameNode *sv) MWRITE(headspritestat,sizeof(headspritestat),1,fil); MWRITE(prevspritestat,sizeof(prevspritestat),1,fil); MWRITE(nextspritestat,sizeof(nextspritestat),1,fil); + MWRITE(&tailspritefree,sizeof(tailspritefree),1,fil); //User information for (i = 0; i < MAXSPRITES; i++) @@ -495,11 +493,6 @@ bool GameInterface::SaveGame(FSaveGameNode *sv) MWRITE(Track[i].TrackPoint, Track[i].NumPoints * sizeof(TRACK_POINT),1,fil); } - int32_t svel = 0, vel = 0, angvel = 0; - MWRITE(&vel,sizeof(vel),1,fil); - MWRITE(&svel,sizeof(svel),1,fil); - MWRITE(&angvel,sizeof(angvel),1,fil); - MWRITE(&loc,sizeof(loc),1,fil); //MWRITE(&oloc,sizeof(oloc),1,fil); //MWRITE(&fsync,sizeof(fsync),1,fil); @@ -748,8 +741,6 @@ bool GameInterface::LoadGame(FSaveGameNode* sv) TerminateLevel(); Terminate3DSounds(); - Terminate3DSounds(); - MREAD(&Level,sizeof(Level),1,fil); MREAD(&Skill,sizeof(Skill),1,fil); @@ -864,6 +855,7 @@ bool GameInterface::LoadGame(FSaveGameNode* sv) MREAD(headspritestat,sizeof(headspritestat),1,fil); MREAD(prevspritestat,sizeof(prevspritestat),1,fil); MREAD(nextspritestat,sizeof(nextspritestat),1,fil); + MREAD(&tailspritefree,sizeof(tailspritefree),1,fil); //User information memset(User, 0, sizeof(User)); @@ -960,11 +952,6 @@ bool GameInterface::LoadGame(FSaveGameNode* sv) } } - int32_t svel, vel, angvel; - MREAD(&vel,sizeof(vel),1,fil); - MREAD(&svel,sizeof(svel),1,fil); - MREAD(&angvel,sizeof(angvel),1,fil); - MREAD(&loc,sizeof(loc),1,fil); MREAD(LevelName,sizeof(LevelName),1,fil); @@ -1225,13 +1212,9 @@ bool GameInterface::LoadGame(FSaveGameNode* sv) MUS_ResumeSaved(); if (snd_ambience) StartAmbientSound(); - FX_SetVolume(snd_fxvolume); TRAVERSE_CONNECT(i) { - Player[i].PlayerTalking = FALSE; - Player[i].TalkVocnum = -1; - Player[i].TalkVocHandle = -1; Player[i].StartColor = 0; } diff --git a/source/sw/src/scrip2.cpp b/source/sw/src/scrip2.cpp index c98ce0b2c..80dcddc2d 100644 --- a/source/sw/src/scrip2.cpp +++ b/source/sw/src/scrip2.cpp @@ -27,7 +27,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "ns.h" // scriplib.c #include "build.h" -#include "cache1d.h" + #include "keys.h" #include "names2.h" @@ -49,8 +49,6 @@ BEGIN_SW_NS //#define COMPUTE_TOTALS 1 -extern int nextvoxid; // JBF: in game.c - ParentalStruct aVoxelArray[MAXTILES]; diff --git a/source/sw/src/sector.cpp b/source/sw/src/sector.cpp index e62347ed8..f6e0d58f8 100644 --- a/source/sw/src/sector.cpp +++ b/source/sw/src/sector.cpp @@ -861,7 +861,7 @@ DoSpawnActorTrigger(short match) if (ActorSpawn(sp)) { DoSpawnTeleporterEffectPlace(sp); - PlaySound(DIGI_PLAYER_TELEPORT, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_PLAYER_TELEPORT, sp, v3df_none); spawn_count++; } } @@ -1242,7 +1242,6 @@ DoSoundSpotMatch(short match, short sound_num, short sound_type) if (TEST_BOOL2(sp)) flags = v3df_follow|v3df_nolookup|v3df_init; - //flags = v3df_follow|v3df_ambient|v3df_nolookup; // play once and only once if (TEST_BOOL1(sp)) @@ -1285,12 +1284,12 @@ DoSoundSpotMatch(short match, short sound_num, short sound_type) if (pp) { if (pp == Player+myconnectindex) - PlayerSound(snd2play,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(snd2play, v3df_dontpan|v3df_follow,pp); } } else { - PlaySound(snd2play, &sp->x, &sp->y, &sp->z, flags); + PlaySound(snd2play, sp, flags); //if (TEST(flags, v3df_follow)) // Just set it anyway Set3DSoundOwner(sn); @@ -1724,68 +1723,68 @@ OperateSprite(short SpriteNum, short player_is_operating) if (sp->lotag == CARGIRL_R0) { if (choose_snd > 700) - PlayerSound(DIGI_JG44052,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG44052, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 500) - PlayerSound(DIGI_JG45014,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG45014, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 250) - PlayerSound(DIGI_JG44068,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG44068, v3df_dontpan|v3df_follow,pp); else - PlayerSound(DIGI_JG45010,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG45010, v3df_dontpan|v3df_follow,pp); } else if (sp->lotag == MECHANICGIRL_R0) { if (choose_snd > 700) - PlayerSound(DIGI_JG44027,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG44027, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 500) - PlayerSound(DIGI_JG44038,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG44038, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 250) - PlayerSound(DIGI_JG44039,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG44039, v3df_dontpan|v3df_follow,pp); else - PlayerSound(DIGI_JG44048,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG44048, v3df_dontpan|v3df_follow,pp); } else if (sp->lotag == SAILORGIRL_R0) { if (choose_snd > 700) - PlayerSound(DIGI_JG45018,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG45018, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 500) - PlayerSound(DIGI_JG45030,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG45030, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 250) - PlayerSound(DIGI_JG45033,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG45033, v3df_dontpan|v3df_follow,pp); else - PlayerSound(DIGI_JG45043,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG45043, v3df_dontpan|v3df_follow,pp); } else if (sp->lotag == PRUNEGIRL_R0) { if (choose_snd > 700) - PlayerSound(DIGI_JG45053,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG45053, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 500) - PlayerSound(DIGI_JG45067,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG45067, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 250) - PlayerSound(DIGI_JG46005,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG46005, v3df_dontpan|v3df_follow,pp); else - PlayerSound(DIGI_JG46010,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_JG46010, v3df_dontpan|v3df_follow,pp); } else if (sp->lotag == TOILETGIRL_R0) { if (choose_snd > 700) - PlayerSound(DIGI_WHATYOUEATBABY,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_WHATYOUEATBABY, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 500) - PlayerSound(DIGI_WHATDIEDUPTHERE,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_WHATDIEDUPTHERE, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 250) - PlayerSound(DIGI_YOUGOPOOPOO,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_YOUGOPOOPOO, v3df_dontpan|v3df_follow,pp); else - PlayerSound(DIGI_PULLMYFINGER,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_PULLMYFINGER, v3df_dontpan|v3df_follow,pp); } else { if (choose_snd > 700) - PlayerSound(DIGI_SOAPYOUGOOD,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_SOAPYOUGOOD, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 500) - PlayerSound(DIGI_WASHWANG,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_WASHWANG, v3df_dontpan|v3df_follow,pp); else if (choose_snd > 250) - PlayerSound(DIGI_DROPSOAP,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_DROPSOAP, v3df_dontpan|v3df_follow,pp); else - PlayerSound(DIGI_REALTITS,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow,pp); + PlayerSound(DIGI_REALTITS, v3df_dontpan|v3df_follow,pp); } } return TRUE; @@ -1795,7 +1794,7 @@ OperateSprite(short SpriteNum, short player_is_operating) // Don't mess with it if it's already going if (u->WaitTics > 0) return TRUE; - PlaySound(DIGI_PFLIP,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_PFLIP, sp, v3df_none); u->WaitTics = SEC(3) + SEC(RANDOM_RANGE(10)); ChangeState(SpriteNum,s_Pachinko1Operate); @@ -1806,7 +1805,7 @@ OperateSprite(short SpriteNum, short player_is_operating) // Don't mess with it if it's already going if (u->WaitTics > 0) return TRUE; - PlaySound(DIGI_PFLIP,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_PFLIP, sp, v3df_none); u->WaitTics = SEC(3) + SEC(RANDOM_RANGE(10)); ChangeState(SpriteNum,s_Pachinko2Operate); @@ -1817,7 +1816,7 @@ OperateSprite(short SpriteNum, short player_is_operating) // Don't mess with it if it's already going if (u->WaitTics > 0) return TRUE; - PlaySound(DIGI_PFLIP,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_PFLIP, sp, v3df_none); u->WaitTics = SEC(3) + SEC(RANDOM_RANGE(10)); ChangeState(SpriteNum,s_Pachinko3Operate); @@ -1828,7 +1827,7 @@ OperateSprite(short SpriteNum, short player_is_operating) // Don't mess with it if it's already going if (u->WaitTics > 0) return TRUE; - PlaySound(DIGI_PFLIP,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_PFLIP, sp, v3df_none); u->WaitTics = SEC(3) + SEC(RANDOM_RANGE(10)); ChangeState(SpriteNum,s_Pachinko4Operate); @@ -1853,7 +1852,7 @@ OperateSprite(short SpriteNum, short player_is_operating) // change the switch state AnimateSwitch(sp, -1); - PlaySound(DIGI_REGULARSWITCH, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_REGULARSWITCH, sp, v3df_none); if (ComboSwitchTest(TAG_COMBO_SWITCH_EVERYTHING, sp->hitag)) { @@ -1866,7 +1865,7 @@ OperateSprite(short SpriteNum, short player_is_operating) // change the switch state AnimateSwitch(sp, -1); - PlaySound(DIGI_REGULARSWITCH, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_REGULARSWITCH, sp, v3df_none); if (ComboSwitchTest(TAG_COMBO_SWITCH_EVERYTHING, sp->hitag)) { @@ -1921,7 +1920,7 @@ OperateSprite(short SpriteNum, short player_is_operating) AnimateSwitch(sp, -1); - PlaySound(DIGI_BIGSWITCH, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_BIGSWITCH, sp, v3df_none); if (sp->hitag) Level = sp->hitag; @@ -1970,7 +1969,7 @@ OperateSprite(short SpriteNum, short player_is_operating) sp->hitag = 0; sp->lotag = 0; - PlaySound(DIGI_REGULARSWITCH, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_REGULARSWITCH, sp, v3df_none); break; } @@ -1990,7 +1989,7 @@ OperateSprite(short SpriteNum, short player_is_operating) sop->ang_tgt = NORM_ANGLE(sop->ang_tgt + 512); - PlaySound(DIGI_BIGSWITCH, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_BIGSWITCH, sp, v3df_none); return TRUE; @@ -2140,8 +2139,7 @@ OperateTripTrigger(PLAYERp pp) case TAG_SECRET_AREA_TRIGGER: if (pp == Player+myconnectindex) - PlayerSound(DIGI_ANCIENTSECRET, &pp->posx, &pp->posy, &pp->posz, - v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_ANCIENTSECRET, v3df_dontpan|v3df_doppler|v3df_follow,pp); sprintf(ds, GStrings("TXTS_SECRET")); SECRET_Trigger(pp->cursectnum); @@ -2244,7 +2242,7 @@ OperateTripTrigger(PLAYERp pp) sector[pp->cursectnum].hitag = 0; sector[pp->cursectnum].lotag = 0; - PlaySound(DIGI_REGULARSWITCH, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_REGULARSWITCH, pp, v3df_none); break; } } @@ -2351,7 +2349,7 @@ SWBOOL NearThings(PLAYERp pp) if (sector[pp->cursectnum].hitag == PLAYER_SOUNDEVENT_TAG) { if (pp == Player+myconnectindex) - PlayerSound(sector[pp->cursectnum].lotag,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(sector[pp->cursectnum].lotag, v3df_follow|v3df_dontpan,pp); return FALSE; } @@ -2370,7 +2368,7 @@ SWBOOL NearThings(PLAYERp pp) if (sp->hitag == PLAYER_SOUNDEVENT_TAG) { if (pp == Player+myconnectindex) - PlayerSound(sp->lotag,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(sp->lotag, v3df_follow|v3df_dontpan,pp); } return FALSE; // Return false so he doesn't grunt } @@ -2381,7 +2379,7 @@ SWBOOL NearThings(PLAYERp pp) if (wall[neartagwall].hitag == PLAYER_SOUNDEVENT_TAG) { if (pp == Player+myconnectindex) - PlayerSound(wall[neartagwall].lotag,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(wall[neartagwall].lotag, v3df_follow|v3df_dontpan,pp); return FALSE; // We are playing a sound so don't return true } return TRUE; @@ -2420,9 +2418,9 @@ SWBOOL NearThings(PLAYERp pp) if (!TEST(wp->extra, WALLFX_DONT_STICK) && pp == Player+myconnectindex) { if (STD_RANDOM_RANGE(1000) > 970) - PlayerSound(DIGI_HITTINGWALLS,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_HITTINGWALLS, v3df_follow|v3df_dontpan,pp); else - PlayerSound(DIGI_SEARCHWALL,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_SEARCHWALL, v3df_follow|v3df_dontpan,pp); } return TRUE; @@ -2581,7 +2579,7 @@ int DoPlayerGrabStar(PLAYERp pp) { // Pull a star out of wall and up your ammo PlayerUpdateAmmo(pp, WPN_STAR, 1); - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_ITEM, sp, v3df_none); KillSprite(StarQueue[i]); StarQueue[i] = -1; if (TEST(pp->WpnFlags, BIT(WPN_STAR))) @@ -3178,7 +3176,7 @@ void movelava(char *dapic) offs2 = (LAVASIZ + 2) + 1 + ((intptr_t) lavabakpic); for (x = 0; x < LAVASIZ; x++) { - memcpy(offs, offs2, LAVASIZ); + copybuf(offs, offs2, LAVASIZ >> 2); offs += LAVASIZ; offs2 += LAVASIZ + 2; } diff --git a/source/sw/src/setup.cpp b/source/sw/src/setup.cpp index 8177426ba..fe8e17c1d 100644 --- a/source/sw/src/setup.cpp +++ b/source/sw/src/setup.cpp @@ -30,12 +30,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "game.h" #include "mytypes.h" -#include "fx_man.h" -#include "music.h" #include "gamedefs.h" -#include "keyboard.h" -#include "control.h" #include "config.h" #include "sounds.h" #include "gamecontrol.h" diff --git a/source/sw/src/skull.cpp b/source/sw/src/skull.cpp index 4ab27072f..137886d5a 100644 --- a/source/sw/src/skull.cpp +++ b/source/sw/src/skull.cpp @@ -472,7 +472,7 @@ int DoSkullWait(short SpriteNum) if ((u->WaitTics -= ACTORMOVETICS) <= 0) { - PlaySound(DIGI_AHSCREAM,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_AHSCREAM, sp, v3df_none); u->WaitTics = SEC(3) + RANDOM_RANGE(360); } @@ -881,7 +881,7 @@ int DoBettyWait(short SpriteNum) if ((u->WaitTics -= ACTORMOVETICS) <= 0) { - PlaySound(DIGI_MINEBEEP,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_MINEBEEP, sp, v3df_none); u->WaitTics = SEC(3); } diff --git a/source/sw/src/sounds.cpp b/source/sw/src/sounds.cpp index 95d534544..da75ec513 100644 --- a/source/sw/src/sounds.cpp +++ b/source/sw/src/sounds.cpp @@ -1,6 +1,7 @@ //------------------------------------------------------------------------- /* Copyright (C) 1997, 2005 - 3D Realms Entertainment +Copyright (C) 2019 Christoph Oelckers This file is part of Shadow Warrior version 1.2 @@ -26,15 +27,12 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "ns.h" #include "compat.h" #include "build.h" -#include "cache1d.h" + #include "keys.h" #include "names2.h" #include "mytypes.h" -#include "fx_man.h" -#include "music.h" -#include "al_midi.h" #include "gamedefs.h" #include "config.h" @@ -52,15 +50,16 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "config.h" #include "menu/menu.h" #include "z_music.h" - -#ifdef _WIN32 -#include "sdlayer.h" -#endif +#include "sound/s_soundinternal.h" +#include "filesystem/filesystem.h" BEGIN_SW_NS -extern USERp User[MAXSPRITES]; -void DumpSounds(void); +enum EChanExFlags +{ + CHANEXF_NODOPPLER = 0x20000000, + CHANEXF_DONTPAN = 0x40000000, +}; // Parentally locked sounds list int PLocked_Sounds[] = @@ -72,49 +71,6 @@ int PLocked_Sounds[] = 558,557 }; - -// Global vars used by ambient sounds to set spritenum of ambient sounds for later lookups in -// the sprite array so FAFcansee can know the sound sprite's current sector location -SWBOOL Use_SoundSpriteNum = FALSE; -int16_t SoundSpriteNum = -1; // Always set this back to -1 for proper validity checking! - -SWBOOL FxInitialized = FALSE; - -void SoundCallBack(unsigned int num); - -#define MUSIC_ID -65536 - -#define NUM_SAMPLES 10 - -const char *BitNames[2] = -{ - "8-bit", "16-bit" -}; - -const char *ChannelNames[2] = -{ - "Mono", "Stereo" -}; - -const char *VoiceNames[8] = -{ - "1", "2", "3", "4", "5", "6", "7", "8" -}; - -int music; -int soundfx; -int num_voices; - -int NumSounds = 0; - -int angle; -int distance; -int voice; - -int loopflag; - -extern SWBOOL DemoMode; - // // Includes digi.h to build the table // @@ -139,26 +95,750 @@ AMB_INFO ambarray[] = #undef AMBIENT_TABLE #define MAX_AMBIENT_SOUNDS 82 -#define MAXSONGS 10 // This is the max songs per episode -SWBOOL OpenSound(VOC_INFOp vp, FileReader &handle, int *length); -int ReadSound(FileReader & handle, VOC_INFOp vp, int length); -// 3d sound engine function prototype -VOC3D_INFOp Insert3DSound(void); +//========================================================================== +// +// +// +//========================================================================== + +float S_ConvertPitch(int lpitch) +{ + return pow(2, lpitch / 1200.); +} + +//========================================================================== +// +// Sound Distance Calculation +// +//========================================================================== + +enum +{ + MAXLEVLDIST = 19000, // The higher the number, the further away you can hear sound + DECAY_CONST = 4000 +}; + +short SoundDist(int x, int y, int z, int basedist) +{ + double tx, ty, tz; + double sqrdist, retval; + extern short screenpeek; + + tx = fabs(Player[screenpeek].posx - x); + ty = fabs(Player[screenpeek].posy - y); + tz = fabs((Player[screenpeek].posz - z) >> 4); + + // Use the Pythagreon Theorem to compute the magnitude of a 3D vector + sqrdist = fabs(tx * tx + ty * ty + tz * tz); + retval = sqrt(sqrdist); + + if (basedist < 0) // if basedist is negative + { + double decayshift = 2; + int decay = labs(basedist) / DECAY_CONST; + + for (int i = 0; i < decay; i++) + decayshift *= 2; + + if (fabs(double(basedist) / decayshift) >= retval) + retval = 0; + else + retval *= decay; + } + else + { + if (basedist > retval) + retval = 0; + else + retval -= basedist; + } + + retval = retval * 256 / MAXLEVLDIST; + + if (retval < 0) retval = 0; + if (retval > 255) retval = 255; + + return retval; +} + +//========================================================================== +// +// Calculate rolloff info. +// +//========================================================================== + +FRolloffInfo GetRolloff(int basedist) +{ + FRolloffInfo info; + + if (basedist < 0) // if basedist is negative + { + double decayshift = 2; + int decay = labs(basedist) / DECAY_CONST; + + for (int i = 0; i < decay; i++) + decayshift *= 2; + + info.RolloffType = ROLLOFF_Doom; + info.MinDistance = (float)(-basedist / decayshift / 16.); + info.MaxDistance = MAXLEVLDIST / 16.f / decay; + } + else + { + info.RolloffType = ROLLOFF_Doom; + info.MinDistance = basedist / 16.f; + info.MaxDistance = info.MinDistance + MAXLEVLDIST / 16.f; + } + return info; +} + + +//========================================================================== +// +// +// Ambient sounds +// +// +//========================================================================== + +struct AmbientSound +{ + SPRITEp sp; + FSoundChan* sndChan; + int ambIndex; + int vocIndex; + int ChanFlags; + int maxIndex; + int curIndex; + bool intermit; +}; + +static TArray ambients; + + +//========================================================================== +// +// +// +//========================================================================== + +void StopAmbientSound(void) +{ + for (auto& amb : ambients) + { + if (amb->sndChan) + { + soundEngine->StopChannel(amb->sndChan); + } + } + ambients.Clear(); +} + + +//========================================================================== +// +// Play a sound +// +//========================================================================== + +void InitAmbient(int num, SPRITEp sp) +{ + VOC_INFOp vp; + int pitch = 0; + short angle, sound_dist; + int tx, ty, tz; + uint8_t priority; + int maxtics = 0; + + if (!snd_ambience) return; + + // Ambient sounds need special treatment + if (num < 0 || num > MAX_AMBIENT_SOUNDS) + { + sprintf(ds, "Invalid or out of range ambient sound number %d\n", num); + PutStringInfo(Player + screenpeek, ds); + return; + } + auto vnum = ambarray[num].diginame; + if (!soundEngine->isValidSoundId(vnum)) + { + return; // linked sound does not exist. + } + + auto amb = new AmbientSound; + amb->sp = sp; + amb->ambIndex = num; + amb->vocIndex = vnum; + amb->sndChan = nullptr; + amb->ChanFlags = 0; + if (ambarray[num].ambient_flags & v3df_dontpan) amb->ChanFlags |= EChanFlags::FromInt(CHANEXF_DONTPAN); + if (voc[vnum].voc_flags & vf_loop) amb->ChanFlags |= CHANF_LOOP; + amb->maxIndex = ambarray[num].maxtics * 8; + amb->curIndex = 0; + amb->intermit = !!(ambarray[num].ambient_flags & v3df_intermit); + ambients.Push(amb); +} + +//========================================================================== +// +// +// +//========================================================================== + +void StartAmbientSound(void) +{ + short i, nexti; + extern SWBOOL InMenuLevel; + + if (InMenuLevel || !SoundEnabled()) return; // Don't restart ambience if no level is active! Will crash game. + + TRAVERSE_SPRITE_STAT(headspritestat[STAT_AMBIENT], i, nexti) + { + SPRITEp sp = &sprite[i]; + InitAmbient(sp->lotag, sp); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +static void RestartAmbient(AmbientSound* amb) +{ + auto& vp = voc[amb->vocIndex]; + auto rolloff = GetRolloff(vp.voc_distance); + int pitch = 0; + if (vp.pitch_hi <= vp.pitch_lo) pitch = vp.pitch_lo; + else pitch = vp.pitch_lo + (STD_RANDOM_RANGE(vp.pitch_hi - vp.pitch_lo)); + + soundEngine->StartSound(SOURCE_Ambient, amb, nullptr, CHAN_BODY, EChanFlags::FromInt(amb->ChanFlags), amb->vocIndex, 1.f, ATTN_NORM, &rolloff, S_ConvertPitch(pitch)); +} +//========================================================================== +// +// +// +//========================================================================== + +static int RandomizeAmbientSpecials(int handle) +{ +#define MAXRNDAMB 12 + int ambrand[] = + { + 56,57,58,59,60,61,62,63,64,65,66,67 + }; + int i; + + // If ambient sound is found in the array, randomly pick a new sound + for (i = 0; i < MAXRNDAMB; i++) + { + if (handle == ambarray[ambrand[i]].diginame) + return ambrand[STD_RANDOM_RANGE(MAXRNDAMB - 1)]; + } + + return -1; +} + +//========================================================================== +// +// +// +//========================================================================== + + +static void DoTimedSound(AmbientSound* amb) +{ + amb->curIndex += synctics; + if (amb->curIndex >= amb->maxIndex) + { + if (amb->sndChan == nullptr) + { + // Check for special case ambient sounds. Since the sound is stopped and doesn't occupy a real channel at this time we can just swap out the sound ID before restarting it. + int ambid = RandomizeAmbientSpecials(amb->vocIndex); + if (ambid != -1) + { + amb->vocIndex = ambid; + amb->maxIndex = STD_RANDOM_RANGE(ambarray[ambid].maxtics); + } + RestartAmbient(amb); + } + amb->curIndex; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +static void UpdateAmbients() +{ + for (auto& amb : ambients) + { + auto sp = amb->sp; + auto sdist = SoundDist(sp->pos.x, sp->pos.y, sp->pos.z, voc[amb->vocIndex].voc_distance); + + if (sdist < 255 && amb->vocIndex == DIGI_WHIPME) + { + PLAYERp pp = Player + screenpeek; + if (!FAFcansee(sp->pos.x, sp->pos.y, sp->pos.z, sp->sectnum, pp->posx, pp->posy, pp->posz, pp->cursectnum)) + { + sdist = 255; + } + } + if (sdist < 255) + { + if (amb->intermit) DoTimedSound(amb); + else RestartAmbient(amb); + + } + else + { + if (amb->sndChan) + { + soundEngine->StopChannel(amb->sndChan); + amb->sndChan = nullptr; + } + } + + } +} + +//========================================================================== +// +// end of ambient sounds +// +//========================================================================== + + + + +//========================================================================== +// +// +// +//========================================================================== + +class SWSoundEngine : public SoundEngine +{ + // client specific parts of the sound engine go in this class. + void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan* chan) override; + TArray ReadSound(int lumpnum) override; + void ChannelEnded(FISoundChannel* chan) override; + +public: + SWSoundEngine() + { + S_Rolloff.RolloffType = ROLLOFF_Doom; + S_Rolloff.MinDistance = 0; // These are the default values, SW uses a few different rolloff settings. + S_Rolloff.MaxDistance = 1187; + } +}; + +//========================================================================== +// +// +// +//========================================================================== + +TArray SWSoundEngine::ReadSound(int lumpnum) +{ + auto wlump = fileSystem.OpenFileReader(lumpnum); + return wlump.Read(); +} + +void SWSoundEngine::ChannelEnded(FISoundChannel* chan) +{ + // if this channel belongs to an ambient sound we have to delete the reference to it. + for (auto amb : ambients) + { + if (amb->sndChan == chan) + { + amb->sndChan = nullptr; + } + } + SoundEngine::ChannelEnded(chan); +} + +//========================================================================== +// +// +// +//========================================================================== + +void InitFX(void) +{ + if (soundEngine) return; // just in case. + soundEngine = new SWSoundEngine; + + auto &S_sfx = soundEngine->GetSounds(); + S_sfx.Resize(countof(voc)); + for (auto& sfx : S_sfx) { sfx.Clear(); sfx.lumpnum = sfx_empty; } + for (size_t i = 1; i < countof(voc); i++) + { + auto& entry = voc[i]; + auto lump = fileSystem.FindFile(entry.name); + if (lump > 0) + { + auto& newsfx = S_sfx[i]; + newsfx.name = entry.name; + newsfx.lumpnum = lump; + newsfx.NearLimit = 6; + newsfx.bTentative = false; + } + } + soundEngine->HashSounds(); + for (auto& sfx : S_sfx) + { + soundEngine->CacheSound(&sfx); + } +} + + + +//========================================================================== +// +// +// +//========================================================================== + +void SWSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan* chan) +{ + if (pos != nullptr) + { + PLAYERp pp = Player + screenpeek; + FVector3 campos = GetSoundPos((vec3_t*)pp); + vec3_t *vpos = nullptr; + + if (vel) vel->Zero(); + + if (type == SOURCE_Unattached) + { + pos->X = pt[0]; + pos->Y = pt[1]; + pos->Z = pt[2]; + } + else if (type == SOURCE_Actor || type == SOURCE_Player) + { + vpos = type == SOURCE_Actor ? &((SPRITEp)source)->pos : (vec3_t*)&((PLAYERp)source)->posx; + FVector3 npos = GetSoundPos(vpos); + + *pos = npos; + if (!(chanflags & CHANEXF_NODOPPLER) && vel) + { + // Hack alert. Velocity may only be set if a) the sound is already running and b) an actual sound channel is modified. + // It remains to be seen if this is actually workable. I have my doubts. The velocity should be taken from a stable source. + if (chan && !(chanflags & (CHANF_JUSTSTARTED | CHANF_EVICTED))) + { + *vel = (npos - FVector3(pt[0], pt[1], pt[2])) * 40; // SW ticks 40 times a second. + chan->Point[0] = npos.X; + chan->Point[1] = npos.Y; + chan->Point[2] = npos.Z; + } + } + } + else if (type == SOURCE_Ambient) + { + auto sp = ((AmbientSound*)source)->sp; + vec3_t* vpos = type == SOURCE_Actor ? &((SPRITEp)source)->pos : (vec3_t*)&((PLAYERp)source)->posx; + FVector3 npos = GetSoundPos(vpos); + + // Can the ambient sound see the player? If not, tone it down some. + if ((chanflags & CHANF_LOOP)) + { + if (!FAFcansee(vpos->x, vpos->y, vpos->z, sp->sectnum, pp->posx, pp->posy, pp->posz, pp->cursectnum)) + { + auto distvec = npos - campos; + npos = campos + distvec * 1.75f; // Play more quietly + } + } + *pos = npos; + } + + if (vpos && chanflags & CHANEXF_DONTPAN) + { + // For unpanned sounds the volume must be set directly and the position taken from the listener. + *pos = campos; + auto sdist = SoundDist(vpos->x, vpos->y, vpos->z, voc[chanSound].voc_distance); + if (chan) SetVolume(chan, (255 - sdist) * (1 / 255.f)); + } + + + if ((chanflags & CHANF_LISTENERZ) && campos != nullptr && type != SOURCE_None) + { + pos->Y = campos.Y; + } + } +} + +//========================================================================== +// +// Main function to update 3D sound array +// +//========================================================================== + +void DoUpdateSounds(void) +{ + PLAYERp pp = Player + screenpeek; + SoundListener listener; + + listener.angle = -(float)pp->pang * pi::pi() / 1024; // Build uses a period of 2048. + listener.velocity.Zero(); + listener.position = GetSoundPos((vec3_t*)&pp->posx); + listener.underwater = false; + // This should probably use a real environment instead of the pitch hacking in S_PlaySound3D. + // listenactor->waterlevel == 3; + //assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber); + listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment; + listener.valid = true; + + listener.ListenerObject = pp; + soundEngine->SetListener(listener); + + UpdateAmbients(); + soundEngine->UpdateSounds((int)totalclock); +} + +//========================================================================== +// +// Play a sound +// +//========================================================================== + +int _PlaySound(int num, SPRITEp sp, PLAYERp pp, vec3_t* pos, Voc3D_Flags flags, int channel) +{ + if (Prediction || !SoundEnabled() || !soundEngine->isValidSoundId(num)) + return -1; + + // Weed out parental lock sounds if PLock is active + if (adult_lockout || Global_PLock) + { + for (unsigned i = 0; i < sizeof(PLocked_Sounds); i++) + { + if (num == PLocked_Sounds[i]) + return -1; + } + } + + auto vp = &voc[num]; + int sourcetype = SOURCE_None; + EChanFlags cflags = channel == 8 ? CHANF_OVERLAP : CHANF_NONE; // for the default channel we do not want to have sounds stopping each other. + void* source = nullptr; + // If the sound is not supposd to be positioned, it may not be linked to the launching actor. + if (!(flags & v3df_follow)) + { + if (sp && !pos) + { + pos = &sp->pos; + sp = nullptr; + } + else if (pp && !pos) + { + pos = (vec3_t*)&pp->posx; + pp = nullptr; + } + } + + if (pos != nullptr) + { + sourcetype = SOURCE_Unattached; + } + else if (sp != nullptr) + { + source = sp; + sourcetype = SOURCE_Actor; + } + else if (pp != nullptr) + { + source = pp; + sourcetype = SOURCE_Player; + } + // Otherwise it's an unpositioned sound. + + if (flags & v3df_doppler) cflags |= EChanFlags::FromInt(CHANEXF_NODOPPLER); // this must ensure that CalcPosVel always zeros the velocity. + if (flags & v3df_dontpan) cflags |= EChanFlags::FromInt(CHANEXF_DONTPAN); // beware of hackery to emulate this. + if (vp->voc_flags & vf_loop) cflags |= CHANF_LOOP; // with the new sound engine these can just be started and don't have to be stopped ever. + + int pitch = 0; + if (vp->pitch_hi <= vp->pitch_lo) pitch = vp->pitch_lo; + else if (vp->pitch_hi != vp->pitch_lo) pitch = vp->pitch_lo + (STD_RANDOM_RANGE(vp->pitch_hi - vp->pitch_lo)); + + auto rolloff = GetRolloff(vp->voc_distance); + FVector3 spos = pos ? GetSoundPos(pos) : FVector3(0, 0, 0); + soundEngine->StartSound(sourcetype, source, &spos, channel, cflags, num, 1.f, ATTN_NORM, &rolloff, S_ConvertPitch(pitch)); + return 1; +} + +//========================================================================== +// +// +// +//========================================================================== + +void PlaySoundRTS(int rts_num) +{ + if (!adult_lockout && SoundEnabled() && RTS_IsInitialized() && snd_speech) + { + auto sid = RTS_GetSoundID(rts_num - 1); + if (sid != -1) + { + soundEngine->StartSound(SOURCE_Unattached, nullptr, nullptr, CHAN_VOICE, 0, sid, 0.8f, ATTN_NONE); + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void COVER_SetReverb(int amt) +{ + FX_SetReverb(amt); +} + +//========================================================================== +// +// Deletes vocs in the 3D sound queue with no owners +// +//========================================================================== + +void DeleteNoSoundOwner(short spritenum) +{ + SPRITEp sp = &sprite[spritenum]; + + soundEngine->EnumerateChannels([=](FSoundChan* chan) + { + if (chan->Source == sp && chan->ChanFlags & CHANF_LOOP) + { + soundEngine->StopChannel(chan); + } + return false; + }); +} + +//========================================================================== +// +// This is called from KillSprite to kill a follow sound with no valid sprite owner +// Stops any active sound with the follow bit set, even play once sounds. +// +//========================================================================== + +void DeleteNoFollowSoundOwner(short spritenum) +{ + SPRITEp sp = &sprite[spritenum]; + soundEngine->StopSound(SOURCE_Actor, sp, -1); // all non-follow sounds are SOURCE_Unattached +} + +//========================================================================== +// +// Terminate the sounds list +// +//========================================================================== + +void Terminate3DSounds(void) +{ + soundEngine->EnumerateChannels([](FSoundChan* chan) + { + if (chan->SourceType == SOURCE_Actor || chan->SourceType == SOURCE_Unattached || + (chan->SourceType == SOURCE_Player && chan->EntChannel != CHAN_VOICE)) + { + soundEngine->StopChannel(chan); + } + return false; + }); +} + + +//========================================================================== +// +// no longer needed, only left to avoid changing the game code +// +//========================================================================== + +void Set3DSoundOwner(short spritenum) +{ + +} + +//========================================================================== +// +// Play a sound using special sprite setup +// +//========================================================================== + +void PlaySpriteSound(short spritenum, int attrib_ndx, Voc3D_Flags flags) +{ + SPRITEp sp = &sprite[spritenum]; + USERp u = User[spritenum]; + + ASSERT(u); + + PlaySound(u->Attrib->Sounds[attrib_ndx], sp, flags); +} + +//========================================================================== +// +// +// +//========================================================================== + +int _PlayerSound(int num, PLAYERp pp) +{ + int handle; + VOC_INFOp vp; + + if (Prediction) + return 0; + + if (pp < Player || pp >= Player + MAX_SW_PLAYERS) + { + return 0; + } + + if (num < 0 || num >= DIGI_MAX || !soundEngine->isValidSoundId(num)) + return 0; + + if (TEST(pp->Flags, PF_DEAD)) return 0; // You're dead, no talking! + + // If this is a player voice and he's already yacking, forget it. + vp = &voc[num]; + + // Not a player voice, bail. + if (vp->priority != PRI_PLAYERVOICE && vp->priority != PRI_PLAYERDEATH) + return 0; + + // He wasn't talking, but he will be now. + if (!soundEngine->IsSourcePlayingSomething(SOURCE_Player, pp, CHAN_VOICE)) + { + soundEngine->StartSound(SOURCE_Player, pp, nullptr, CHAN_VOICE, 0, num, 1.f, ATTN_NORM); + } + + return 0; +} + +void StopPlayerSound(PLAYERp pp) +{ + soundEngine->StopSound(SOURCE_Player, pp, CHAN_VOICE); +} + +bool SoundValidAndActive(SPRITEp spr, int channel) +{ + return soundEngine->IsSourcePlayingSomething(SOURCE_Actor, spr, channel); +} -#if 0 -// DEBUG -char *globsndata[DIGI_MAX], *globvpdata[DIGI_MAX]; -int glength[DIGI_MAX]; -#endif /* -=================== +============================================================================ = -= My stuff += High level sound code (not directly engine related) = -=================== +============================================================================ */ int PlayerPainVocs[] = @@ -234,71 +914,11 @@ int PlayerYellVocs[] = }; +//========================================================================== // -// Routine called when a sound is finished playing +// PLays music // - -void -SoundCallBack(intptr_t num) -{ - VOC_INFOp vp; - - if ((int) num == MUSIC_ID) - { - return; - } - - // RTS sounds are negative - if ((int)num < 0) - { - return; - } - - vp = &voc[num]; - - // Update counter - //vp->playing--; - vp->lock--; -} - -// - -void -ClearSoundLocks(void) -{ - unsigned i; - - for (i = 0; i < SIZ(voc); i++) - { - if (voc[i].lock >= 200) - voc[i].lock = 199; - } -} - -void -UnInitSound(void) -{ - SoundShutdown(); - Mus_Stop(); -} - -void -InitFX(void) -{ - VOC_INFOp vp; - short i; - - // Select which cards to use - SoundStartup(); - - for (vp = voc; vp < &voc[SIZ(voc)]; vp++) - { - vp->playing = 0; - } - - // Set up our fx callback so we can display the sounds that are playing - FX_SetCallBack(SoundCallBack); -} +//========================================================================== extern short Level; CVAR(Bool, sw_nothememidi, false, CVAR_ARCHIVE) @@ -323,1336 +943,11 @@ SWBOOL PlaySong(const char* mapname, const char* song_file_name, int cdaudio_tra return Mus_Play(nullptr, song_file_name, true); } -void -StopFX(void) +void StopSound(void) { - FX_StopAllSounds(); -} - -void -StopSound(void) -{ - StopFX(); + soundEngine->StopAllChannels(); Mus_Stop(); } -// -// Sound Distance Calculation -// - -#define MAXLEVLDIST 19000 // The higher the number, the further away you can hear sound - -short SoundDist(int x, int y, int z, int basedist) -{ - double tx, ty, tz; - double sqrdist,retval; - double decay,decayshift; - extern short screenpeek; - -#define DECAY_CONST 4000 - - - tx = fabs(Player[screenpeek].posx - x); - ty = fabs(Player[screenpeek].posy - y); - tz = fabs((Player[screenpeek].posz - z) >> 4); - - // Use the Pythagreon Theorem to compute the magnitude of a 3D vector - sqrdist = fabs(tx*tx + ty*ty + tz*tz); - retval = sqrt(sqrdist); - - if (basedist < 0) // if basedist is negative - { - short i; - - decayshift=2; - decay = labs(basedist) / DECAY_CONST; - - for (i=0; i= retval) - retval = 0; - else - retval *= decay; - } - else - { - if (basedist > retval) - retval = 0; - else - retval -= basedist; - } - - retval = retval * 256 / MAXLEVLDIST; - - if (retval < 0) retval = 0; - if (retval > 255) retval = 255; - - return retval; -} - -// -// Angle calcuations - may need to be checked to make sure they are right -// - -short SoundAngle(int x, int y) -{ - extern short screenpeek; - - short angle, delta_angle; - - angle = getangle(x - Player[screenpeek].posx, y - Player[screenpeek].posy); - - delta_angle = GetDeltaAngle(angle, Player[screenpeek].pang); - - // convert a delta_angle to a real angle if negative - if (delta_angle < 0) - delta_angle = NORM_ANGLE((1024 + delta_angle) + 1024); - - // convert 2048 degree angle to 128 degree angle - return delta_angle >> 4; -} - -int _PlayerSound(const char *file, int line, int num, int *x, int *y, int *z, Voc3D_Flags flags, PLAYERp pp) -//PlayerSound(int num, int *x, int *y, int *z, Voc3D_Flags flags, PLAYERp pp) -{ - int handle; - VOC_INFOp vp; - - if (Prediction) - return 0; - - if (pp < Player || pp >= Player + MAX_SW_PLAYERS) - { - TerminateGame(); - printf("Player Sound invalid player: file %s, line %d\n",file,line); - exit(0); - } - - PRODUCTION_ASSERT(pp >= Player && pp < Player+MAX_SW_PLAYERS); - PRODUCTION_ASSERT(num >= 0 && num < DIGI_MAX); - - if (TEST(pp->Flags, PF_DEAD)) return 0; // You're dead, no talking! - - // If this is a player voice and he's already yacking, forget it. - vp = &voc[num]; - if (vp == NULL) - { - TerminateGame(); - printf("vp == NULL in PlayerSound, num = %d\n",num); - exit(0); - } - - // Not a player voice, bail. - if (vp->priority != PRI_PLAYERVOICE && vp->priority != PRI_PLAYERDEATH) - return 0; - - // He wasn't talking, but he will be now. - if (!pp->PlayerTalking) - { - pp->PlayerTalking = TRUE; - pp->TalkVocnum = num; // Set the voc number - pp->TalkVocHandle = PlaySound(num, x, y, z, flags); // Play the sound - if (pp->TalkVocHandle < 0) - { - pp->PlayerTalking = FALSE; - pp->TalkVocnum = -1; - pp->TalkVocHandle = -1; - } - } - - return 0; -} - -void LockSound(int num) -{ - VOC_INFOp vp = &voc[num]; - // if data is not locked - if (vp->lock <= CACHE_UNLOCK_MAX) - { - vp->lock = CACHE_LOCK_START; - } - else - // if data is already locked - { - vp->lock++; - if (vp->lock >= CACHE_LOCK_MAX || vp->lock == 0) - { - DumpSounds(); - TerminateGame(); - printf("lock > MAX, num = %d",num); - exit(0); - } - //ASSERT(vp->lock < CACHE_LOCK_MAX); - //ASSERT(vp->lock != 0); - } -} - -SWBOOL CacheSound(int num, int type) -{ - VOC_INFOp vp = &voc[num]; - - PRODUCTION_ASSERT(num >= 0 && num < DIGI_MAX); - - // if no data we need to cache it in - if (!vp->data) - { - FileReader handle; - int length; - - if (!OpenSound(vp, handle, &length)) - { - sprintf(ds,"Could not open sound %s, num %d, priority %d\n",vp->name,num,vp->priority); - OSD_Printf("%s", ds); - return FALSE; - } - - if (vp != NULL) - { - //FILE *fp; - - /* - if (type == CACHE_SOUND_PLAY) - // start it out locked at the min - vp->lock = CACHE_LOCK_START; - else - if (type == CACHE_SOUND_PRECACHE) - // start it out unlocked at the max - */ - vp->lock = CACHE_UNLOCK_MAX; - - cacheAllocateBlock((intptr_t*)&vp->data, length, &vp->lock); - - /////// - - ASSERT(vp->data); - ReadSound(handle, vp, length); - - } - } - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////////// -// Play a sound -//////////////////////////////////////////////////////////////////////////// - -#define SOUND_UNIT MAXLEVLDIST/255 -// NOTE: If v3df_follow == 1, x,y,z are considered literal coordinates -int PlaySound(int num, int *x, int *y, int *z, Voc3D_Flags flags) -{ - VOC_INFOp vp; - VOC3D_INFOp v3p; - int pitch = 0; - short angle, sound_dist; - int tx, ty, tz; - uint8_t priority; - SPRITEp sp=NULL; - - // DEBUG - //extern SWBOOL Pachinko_Win_Cheat; - - - // Don't play game sounds when in menus - //if (M_Active() && (*x!=0 || *y!=0 || *z!=0)) return(-1); - - // Weed out parental lock sounds if PLock is active - if (adult_lockout || Global_PLock) - { - unsigned i; - - for (i=0; i= 0 && num < DIGI_MAX); - - // Reset voice - voice = -1; - - // This is used for updating looping sounds in Update3DSounds - if (Use_SoundSpriteNum && SoundSpriteNum >= 0) - { - ASSERT(SoundSpriteNum >= 0 && SoundSpriteNum < MAXSPRITES); - sp = &sprite[SoundSpriteNum]; - } - - if (snd_ambience && TEST(flags,v3df_ambient) && !TEST(flags,v3df_nolookup)) // Look for invalid ambient numbers - { - if (num < 0 || num > MAX_AMBIENT_SOUNDS) - { - sprintf(ds,"Invalid or out of range ambient sound number %d\n",num); - PutStringInfo(Player+screenpeek, ds); - return -1; - } - } - - - // Call queue management to add sound to play list. - // 3D sound manager will update playing sound 10x per second until - // the sound ends, at which time it is removed from both the 3D - // sound list as well as the actual cache. - v3p = Insert3DSound(); - - // If the ambient flag is set, do a name conversion to point to actual - // digital sound entry. - v3p->num = num; - v3p->priority = 0; - v3p->FX_Ok = FALSE; // Hasn't played yet - - if (snd_ambience && TEST(flags,v3df_ambient) && !TEST(flags,v3df_nolookup)) - { - v3p->maxtics = STD_RANDOM_RANGE(ambarray[num].maxtics); - flags |= ambarray[num].ambient_flags; // Add to flags if any - num = ambarray[num].diginame; - } - - PRODUCTION_ASSERT(num >= 0 && num < DIGI_MAX); - - - // Assign voc to voc pointer - vp = &voc[num]; - if (M_Active() && *x==0 && *y==0 && *z==0) // Menus sound outdo everything - priority = 100; - else - priority = vp->priority; - v3p->vp = vp; - - // Assign voc info to 3d struct for future reference - v3p->x = x; - v3p->y = y; - v3p->z = z; - v3p->fx = *x; - v3p->fy = *y; - v3p->fz = *z; - v3p->flags = flags; - - if (flags & v3df_follow) - { - tx = *x; - ty = *y; - if (!z) - tz = 0; // Some sound calls don't have a z - // value - else - tz = *z; - } - else - { - // Don't use pointers to coordinate values. - tx = v3p->fx; - ty = v3p->fy; - tz = v3p->fz; - } - - // Special case stuff for sounds being played in a level - if (*x==0 && *y==0 && *z==0) - tx = ty = tz = 0; - - if ((vp->voc_flags & vf_loop) && Use_SoundSpriteNum && SoundSpriteNum >= 0 && sp) - { - tx=sp->x; - ty=sp->y; - tz=sp->z; - //CON_Message("Using sp to set tx=%ld,ty=%ld,tz=%ld",tx,ty,tz); - } - - // Calculate sound angle - if (flags & v3df_dontpan) // If true, don't do panning - angle = 0; - else - angle = SoundAngle(tx, ty); - - // Calculate sound distance - if (tx == 0 && ty == 0 && tz == 0) - sound_dist = 255; // Special case for menus sounds,etc. - else - sound_dist = SoundDist(tx, ty, tz, vp->voc_distance); - - v3p->doplr_delta = sound_dist; // Save of distance for doppler - // effect - -// //DSPRINTF(ds,"sound dist = %d\n",sound_dist); -// MONO_PRINT(ds); - - // Can the ambient sound see the player? If not, tone it down some. - if ((vp->voc_flags & vf_loop) && Use_SoundSpriteNum && SoundSpriteNum >= 0) - { - PLAYERp pp = Player+screenpeek; - - //MONO_PRINT("PlaySound:Checking sound cansee"); - if (!FAFcansee(tx, ty, tz, sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum)) - { - //MONO_PRINT("PlaySound:Reducing sound distance"); - sound_dist += ((sound_dist/2)+(sound_dist/4)); // Play more quietly - if (sound_dist > 255) sound_dist = 255; - - // Special Cases - if (num == DIGI_WHIPME) sound_dist = 255; - } - } - - // Assign ambient priorities based on distance - if (snd_ambience && TEST(flags, v3df_ambient)) - { - v3p->priority = v3p->vp->priority - (sound_dist / 26); - priority = v3p->priority; - } - - if (!CacheSound(num, CACHE_SOUND_PLAY)) - { - v3p->flags = v3df_kill; - v3p->handle = -1; - v3p->dist = 0; - v3p->deleted = TRUE; // Sound init failed, remove it! - return -1; - } - - LockSound(num); - - if (sound_dist < 5) - angle = 0; - - // Check for pitch bending - if (vp->pitch_lo > vp->pitch_hi) - ASSERT(vp->pitch_lo <= vp->pitch_hi); - - if (vp->pitch_hi == vp->pitch_lo) - pitch = vp->pitch_lo; - else if (vp->pitch_hi != vp->pitch_lo) - pitch = vp->pitch_lo + (STD_RANDOM_RANGE(vp->pitch_hi - vp->pitch_lo)); - -#if 0 - // DEBUG - if (Pachinko_Win_Cheat) - { - CheckSndData(__FILE__, __LINE__); - Pachinko_Win_Cheat = FALSE; - CON_Message("S O U N D S C H E C K E D"); - } -#endif - - // Request playback and play it as a looping sound if flag is set. - if (vp->voc_flags & vf_loop) - { - short loopvol=0; - - if ((loopvol = 255-sound_dist) <= 0) - loopvol = 0; - - if (sound_dist < 255 || (flags & v3df_init)) - { - voice = FX_Play((char *)vp->data, vp->datalen, 0, 0, - pitch, loopvol, loopvol, loopvol, priority, 1.f, num); // [JM] Should probably utilize floating point volume. !CHECKME! - } - else - voice = -1; - - } - else - //if(!flags & v3df_init) // If not initing sound, play it - if (tx==0 && ty==0 && tz==0) // It's a non-inlevel sound - { - voice = FX_Play((char *)vp->data, vp->datalen, -1, -1, pitch, 255, 255, 255, priority, 1.f, num); // [JM] And here !CHECKME! - } - else // It's a 3d sound - { - if (sound_dist < 255) - { - voice = FX_Play3D((char *)vp->data, vp->datalen, FX_ONESHOT, pitch, angle, sound_dist, priority, 1.f, num); // [JM] And here !CHECKME! - } - else - voice = -1; - } - - // If sound played, update our counter - if (voice > FX_Ok) - { - //vp->playing++; - v3p->FX_Ok = TRUE; - } - else - { - vp->lock--; - } - - // Assign voc info to 3d struct for future reference - v3p->handle = voice; // Save the current voc handle in struct - v3p->dist = sound_dist; - v3p->tics = 0; // Reset tics - if (flags & v3df_init) - v3p->flags ^= v3df_init; // Turn init off now - - return voice; -} - -void PlaySoundRTS(int rts_num) -{ - char *rtsptr; - int voice=-1; - - if (!RTS_IsInitialized() || !SoundEnabled()) - return; - - rtsptr = (char *)RTS_GetSound(rts_num - 1); - - ASSERT(rtsptr); - - voice = FX_Play3D(rtsptr, RTS_SoundLength(rts_num - 1), FX_ONESHOT, 0, 0, 0, 255, 1.f, -rts_num); // [JM] Float volume here too I bet. !CHECKME! -} - -/////////////////////////////////////////////// - -SWBOOL -OpenSound(VOC_INFOp vp, FileReader &handle, int *length) -{ - handle = fileSystem.OpenFileReader(vp->name, 0); - - if (!handle.isOpen()) - { - return FALSE; - } - - *length = handle.GetLength(); - - return TRUE; -} - - -int -ReadSound(FileReader &handle, VOC_INFOp vp, int length) -{ - if (handle.Read(vp->data, length) != length) - { - TerminateGame(); - printf("Error reading file '%s'.\n", vp->name); - exit(0); - } - - vp->datalen = length; - return 0; -} - -void -SoundStartup(void) -{ - void *initdata = 0; - - -#ifdef MIXERTYPEWIN - initdata = (void *) win_gethwnd(); -#endif - - //snd_enabled = TRUE; - - - int status = FX_Init(snd_numvoices, snd_numchannels, snd_mixrate, initdata); - if (status != FX_Ok) - { - buildprintf("Sound error: %s\n", FX_ErrorString(status)); - return; - } - - FxInitialized = TRUE; - snd_fxvolume.Callback(); - snd_reversestereo.Callback(); - - FX_SetCallBack(SoundCallBack); -} - -/* -=================== -= -= SoundShutdown -= -=================== -*/ - -void -SoundShutdown(void) -{ - if (!FxInitialized) - return; - - int status = FX_Shutdown(); - if (status != FX_Ok) - { - buildprintf("Sound error: %s\n", FX_ErrorString(status)); - } -} - - -void COVER_SetReverb(int amt) -{ - FX_SetReverb(amt); -} - -/////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////// -// -// 3D sound engine -// Sound management routines that keep a list of -// all sounds being played in a level. -// Doppler and Panning effects are achieved here. -// -/////////////////////////////////////////////// -// Declare and initialize linked list of vocs. -VOC3D_INFOp voc3dstart = NULL; -VOC3D_INFOp voc3dend = NULL; - -////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////// -// Initialize new vocs in the 3D sound queue -/////////////////////////////////////////////// -VOC3D_INFOp -InitNew3DSound(VOC3D_INFOp v3p) -{ - v3p->handle = -1; // Initialize handle to new sound - // value - v3p->owner = -1; - v3p->deleted = FALSE; // Used for when sound gets deleted - - return v3p; -} - -/////////////////////////////////////////////// -// Inserts new vocs in the 3D sound queue -/////////////////////////////////////////////// -VOC3D_INFOp -Insert3DSound(void) -{ - VOC3D_INFOp vp, old; - - // Allocate memory for new sound - // You can allocate new sounds as long as memory holds out. - // If you run out of memory for sounds, you got problems anyway. - vp = (VOC3D_INFOp) AllocMem(sizeof(VOC3D_INFO)); - ASSERT(vp != NULL); - memset(vp,0xCC,sizeof(VOC3D_INFO)); // Zero out the memory - - if (!voc3dend) // First item in list - { - vp->next = vp->prev = NULL; - voc3dend = vp; - voc3dstart = vp; - InitNew3DSound(vp); - return vp; - } - - old = voc3dend; // Put it on the end - old->next = vp; - vp->next = NULL; - vp->prev = old; - voc3dend = vp; - - InitNew3DSound(vp); - return vp; - -} - -///////////////////////////////////////////////////// -// Deletes vocs in the 3D sound queue with no owners -///////////////////////////////////////////////////// -void -DeleteNoSoundOwner(short spritenum) -{ - VOC3D_INFOp vp, dp; - - vp = voc3dstart; - - while (vp) - { - dp = NULL; - if (vp->owner == spritenum && vp->owner >= 0 && (vp->vp->voc_flags & vf_loop)) - { - //DSPRINTF(ds,"Deleting owner %d\n",vp->owner); - //MONO_PRINT(ds); - - // Make sure to stop active - // sounds - if (FX_SoundValidAndActive(vp->handle)) - { - FX_StopSound(vp->handle); - vp->handle = 0; - } - -#if 0 - // Clean up the sound active counter for cacheing locks - if (vp->FX_Ok) // Only decrement if sound ever played - vp->vp->playing--; // Decrement instance of sound playing - if (vp->vp->playing == 0 && vp->vp->lock > CACHE_UNLOCK_MAX) - vp->vp->lock = CACHE_UNLOCK_MAX; -#endif - - - dp = vp; // Point to sound to be deleted - - if (vp->prev) - { - vp->prev->next = vp->next; - } - else - { - voc3dstart = vp->next; // New first item - if (voc3dstart) - voc3dstart->prev = NULL; - } - - if (vp->next) - { - vp->next->prev = vp->prev; // Middle element - } - else - { - voc3dend = vp->prev; // Delete last element - } - } - - vp = vp->next; - - if (dp != NULL) - FreeMem(dp); // Return memory to heap - } -} - -// This is called from KillSprite to kill a follow sound with no valid sprite owner -// Stops and active sound with the follow bit set, even play once sounds. -void DeleteNoFollowSoundOwner(short spritenum) -{ - VOC3D_INFOp vp, dp; - SPRITEp sp = &sprite[spritenum]; - - vp = voc3dstart; - - while (vp) - { - dp = NULL; - // If the follow flag is set, compare the x and y addresses. - if ((vp->flags & v3df_follow) && vp->x == &sp->x && vp->y == &sp->y) - { - if (FX_SoundValidAndActive(vp->handle)) - { - FX_StopSound(vp->handle); - vp->handle = 0; - } - -#if 0 - if (vp->FX_Ok) // Only decrement if sound ever played - vp->vp->playing--; // Decrement instance of sound playing - if (vp->vp->playing == 0 && vp->vp->lock > CACHE_UNLOCK_MAX) - vp->vp->lock = CACHE_UNLOCK_MAX; -#endif - - dp = vp; // Point to sound to be deleted - - if (vp->prev) - { - vp->prev->next = vp->next; - } - else - { - voc3dstart = vp->next; // New first item - if (voc3dstart) - voc3dstart->prev = NULL; - } - - if (vp->next) - { - vp->next->prev = vp->prev; // Middle element - } - else - { - voc3dend = vp->prev; // Delete last element - } - } - - vp = vp->next; - - if (dp != NULL) - FreeMem(dp); // Return memory to heap - } -} - -/////////////////////////////////////////////// -// Deletes vocs in the 3D sound queue -/////////////////////////////////////////////// -void -Delete3DSounds(void) -{ - VOC3D_INFOp vp, dp; - PLAYERp pp; - int cnt=0; - - - vp = voc3dstart; - - while (vp) - { - dp = NULL; - if (vp->deleted) - { -#if 0 - if (vp->FX_Ok) // Only decrement if sound ever played - vp->vp->playing--; // Decrement instance of sound playing - if (vp->vp->playing == 0 && vp->vp->lock > CACHE_UNLOCK_MAX) - vp->vp->lock = CACHE_UNLOCK_MAX; -#endif - - //DSPRINTF(ds,"Delete3DSounds: deleting owner %d digi %d\n",vp->owner,vp->num); - //MONO_PRINT(ds); - // Reset Player talking flag if a voice was deleted - //if(vp->num > DIGI_FIRSTPLAYERVOICE && vp->num < DIGI_LASTPLAYERVOICE) - if (!vp->vp) - { - printf("Delete3DSounds(): NULL vp->vp\n"); - } - else // JBF: added null check - if (vp->vp->priority == PRI_PLAYERVOICE || vp->vp->priority == PRI_PLAYERDEATH) - { - int16_t pnum; - - TRAVERSE_CONNECT(pnum) - { - pp = &Player[pnum]; - - if (vp->num == pp->TalkVocnum) - { - pp->PlayerTalking = FALSE; - pp->TalkVocnum = -1; - pp->TalkVocHandle = -1; - //DSPRINTF(ds,"DELETED PLAYER VOICE VOC! NUM=%d\n",vp->num); - //MONO_PRINT(ds); - } - } - } - - dp = vp; // Point to sound to be deleted - if (vp->prev) - { - vp->prev->next = vp->next; - } - else - { - voc3dstart = vp->next; // New first item - if (voc3dstart) - voc3dstart->prev = NULL; - } - - if (vp->next) - { - vp->next->prev = vp->prev; // Middle element - } - else - { - voc3dend = vp->prev; // Delete last element - } - } - - vp = vp->next; - - if (dp != NULL) - { - FreeMem(dp); // Return memory to heap - } - } -} - -//////////////////////////////////////////////////////////////////////////// -// Play a sound -//////////////////////////////////////////////////////////////////////////// - -int -RandomizeAmbientSpecials(int handle) -{ -#define MAXRNDAMB 12 - int ambrand[] = - { - 56,57,58,59,60,61,62,63,64,65,66,67 - }; - short i; - - // If ambient sound is found in the array, randomly pick a new sound - for (i=0; itics += synctics; - - if (p->tics >= p->maxtics) - { - if (!FX_SoundValidAndActive(p->handle)) - { - // Check for special case ambient sounds - p->num = RandomizeAmbientSpecials(p->num); - - // Sound was bumped from active sounds list, try to play again. - // Don't bother if voices are already maxed out. - if (FX_SoundsPlaying() < snd_numvoices) - { - if (p->flags & v3df_follow) - { - PlaySound(p->num, p->x, p->y, p->z, p->flags); - p->deleted = TRUE; // Mark old sound for deletion - } - else - { - PlaySound(p->num, &p->fx, &p->fy, &p->fz, p->flags); - p->deleted = TRUE; // Mark old sound for deletion - } - } - } - - p->tics = 0; - //while (p->tics >= p->maxtics) // Really stupid thing to do! - // { - // p->tics -= p->maxtics; - // } - } -} - -void -StopAmbientSound(void) -{ - VOC3D_INFOp p; - extern SWBOOL InMenuLevel; - - if (InMenuLevel) return; - - p = voc3dstart; - - while (p) - { - // kill ambient sounds if Ambient is off - if (TEST(p->flags,v3df_ambient)) - SET(p->flags, v3df_kill); - - if (p->flags & v3df_kill) - { - if (FX_SoundValidAndActive(p->handle)) - { - FX_StopSound(p->handle); // Make sure to stop active sounds - p->handle = 0; - } - - p->deleted = TRUE; - } - - p = p->next; - } - - Delete3DSounds(); -} - -void -StartAmbientSound(void) -{ - VOC3D_INFOp p; - short i,nexti; - extern SWBOOL InMenuLevel; - - if (InMenuLevel) return; // Don't restart ambience if no level is active! Will crash game. - - TRAVERSE_SPRITE_STAT(headspritestat[STAT_AMBIENT], i, nexti) - { - SPRITEp sp = &sprite[i]; - - PlaySound(sp->lotag, &sp->x, &sp->y, &sp->z, v3df_ambient | v3df_init - | v3df_doppler | v3df_follow); - Set3DSoundOwner(i); // Ambient sounds need this to get sectnum for later processing - } -} - -/////////////////////////////////////////////// -// Main function to update 3D sound array -/////////////////////////////////////////////// -typedef struct -{ - VOC3D_INFOp p; - short dist; - uint8_t priority; -} TVOC_INFO, *TVOC_INFOp; - -void -DoUpdateSounds3D(void) -{ - VOC3D_INFOp p; - SWBOOL looping; - int pitch = 0, pitchmax; - int delta; - short dist, angle; - SWBOOL deletesound = FALSE; - - TVOC_INFO TmpVocArray[32]; - int i; - static SWBOOL MoveSkip8 = 0; - - if (M_Active()) return; - - // This function is already only call 10x per sec, this widdles it down even more! - MoveSkip8 = (MoveSkip8 + 1) & 15; - - //CON_Message("Sounds Playing = %d",FX_SoundsPlaying()); - - // Zero out the temporary array - //memset(&TmpVocArray[0],0,sizeof(TmpVocArray)); - for (i=0; i<32; i++) - { - TmpVocArray[i].p = NULL; - TmpVocArray[i].dist = 0; - TmpVocArray[i].priority = 0; - } - - p = voc3dstart; - - while (p) - { - ASSERT(p->num >= 0 && p->num < DIGI_MAX); - - looping = p->vp->voc_flags & vf_loop; - -// //DSPRINTF(ds,"sound %d FX_SoundActive = %d\n,",p->num,FX_SoundActive(p->handle)); -// MONO_PRINT(ds); - - // If sprite owner is dead, kill this sound as long as it isn't ambient - if (looping && p->owner == -1 && !TEST(p->flags,v3df_ambient)) - { - SET(p->flags, v3df_kill); - } - - // Is the sound slated for death? Kill it, otherwise play it. - if (p->flags & v3df_kill) - { - if (FX_SoundValidAndActive(p->handle)) - { - FX_StopSound(p->handle); // Make sure to stop active sounds - p->handle = 0; - } - - //DSPRINTF(ds,"%d had v3df_kill.\n",p->num); - //MONO_PRINT(ds); - p->deleted = TRUE; - } - else - { - if (!FX_SoundValidAndActive(p->handle) && !looping) - { - if (p->flags & v3df_intermit) - { - DoTimedSound(p); - } - else - //if(p->owner == -1 && !TEST(p->flags,v3df_ambient)) - { - //DSPRINTF(ds,"%d is now inactive.\n",p->num); - //MONO_PRINT(ds); - p->deleted = TRUE; - } - } - else if (FX_SoundValidAndActive(p->handle)) - { - if (p->flags & v3df_follow) - { - dist = SoundDist(*p->x, *p->y, *p->z, p->vp->voc_distance); - angle = SoundAngle(*p->x, *p->y); - } - else - { - if (p->fx == 0 && p->fy == 0 && p->fz == 0) - dist = 0; - else - dist = SoundDist(p->fx, p->fy, p->fz, p->vp->voc_distance); - angle = SoundAngle(p->fx, p->fy); - } - - // Can the ambient sound see the player? If not, tone it down some. - if ((p->vp->voc_flags & vf_loop) && p->owner != -1) - { - PLAYERp pp = Player+screenpeek; - SPRITEp sp = &sprite[p->owner]; - - //MONO_PRINT("Checking sound cansee"); - if (!FAFcansee(sp->x, sp->y, sp->z, sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum)) - { - //MONO_PRINT("Reducing sound distance"); - dist += ((dist/2)+(dist/4)); // Play more quietly - if (dist > 255) dist = 255; - - // Special cases - if (p->num == 76 && TEST(p->flags,v3df_ambient)) - { - dist = 255; // Cut off whipping sound, it's secret - } - - } - } - - if (dist >= 255 && p->vp->voc_distance == DIST_NORMAL) - { - FX_StopSound(p->handle); // Make sure to stop active - p->handle = 0; - // sounds - } - else - { - // Handle Panning Left and Right - if (!(p->flags & v3df_dontpan)) - FX_Pan3D(p->handle, angle, dist); - else - FX_Pan3D(p->handle, 0, dist); - - // Handle Doppler Effects -#define DOPPLERMAX 400 - if (!(p->flags & v3df_doppler) && FX_SoundActive(p->handle)) - { - pitch -= (dist - p->doplr_delta); - - if (p->vp->pitch_lo != 0 && p->vp->pitch_hi != 0) - { - if (abs(p->vp->pitch_lo) > abs(p->vp->pitch_hi)) - pitchmax = abs(p->vp->pitch_lo); - else - pitchmax = abs(p->vp->pitch_hi); - - } - else - pitchmax = DOPPLERMAX; - - if (pitch > pitchmax) - pitch = pitchmax; - if (pitch < -pitchmax) - pitch = -pitchmax; - - p->doplr_delta = dist; // Save new distance to - // struct - FX_SetPitch(p->handle, pitch); - } - } - } - else if (!FX_SoundValidAndActive(p->handle) && looping) - { - if (p->flags & v3df_follow) - { - dist = SoundDist(*p->x, *p->y, *p->z, p->vp->voc_distance); - angle = SoundAngle(*p->x, *p->y); - } - else - { - dist = SoundDist(p->fx, p->fy, p->fz, p->vp->voc_distance); - angle = SoundAngle(p->fx, p->fy); - } - - // Sound was bumped from active sounds list, try to play - // again. - // Don't bother if voices are already maxed out. - // Sort looping vocs in order of priority and distance - //if (FX_SoundsPlaying() < snd_numvoices && dist <= 255) - if (dist <= 255) - { - for (i=0; ipriority >= TmpVocArray[i].priority) - { - if (!TmpVocArray[i].p || dist < TmpVocArray[i].dist) - { - ASSERT(p->num >= 0 && p->num < DIGI_MAX); - TmpVocArray[i].p = p; - TmpVocArray[i].dist = dist; - TmpVocArray[i].priority = p->priority; - break; - } - } - } - } - } // !FX_SoundActive - } // if(p->flags & v3df_kill) - - p = p->next; - } // while(p) - -// //DSPRINTF(ds,"Num vocs in list: %d, Sounds playing: %d\n",numelems,FX_SoundsPlaying()); -// MONO_PRINT(ds); - - // Process all the looping sounds that said they wanted to get back in - // Only update these sounds 5x per second! Woo hoo!, aren't we optimized now? - //if(MoveSkip8==0) - // { - for (i=0; i= snd_numvoices || !p) break; - if (!p) break; - - ASSERT(p->num >= 0 && p->num < DIGI_MAX); - - if (p->flags & v3df_follow) - { - if (p->owner == -1) - { - int enumber; - enumber = p->num; - TerminateGame(); - printf("Owner == -1 on looping sound with follow flag set!\n"); - printf("p->num = %d\n",enumber); - exit(0); - } - - Use_SoundSpriteNum = TRUE; - SoundSpriteNum = p->owner; - - handle = PlaySound(p->num, p->x, p->y, p->z, p->flags); - //if(handle >= 0 || TEST(p->flags,v3df_ambient)) // After a valid PlaySound, it's ok to use voc3dend - voc3dend->owner = p->owner; // Transfer the owner - p->deleted = TRUE; - - Use_SoundSpriteNum = FALSE; - SoundSpriteNum = -1; - - //MONO_PRINT("TmpVocArray playing a follow sound"); - } - else - { - if (p->owner == -1) - { - int enumber; - enumber = p->num; - TerminateGame(); - printf("Owner == -1 on looping sound, no follow flag.\n"); - printf("p->num = %d\n",enumber); - exit(0); - } - - Use_SoundSpriteNum = TRUE; - SoundSpriteNum = p->owner; - - handle = PlaySound(p->num, &p->fx, &p->fy, &p->fz, p->flags); - //if(handle >= 0 || TEST(p->flags,v3df_ambient)) - voc3dend->owner = p->owner; // Transfer the owner - p->deleted = TRUE; - - Use_SoundSpriteNum = FALSE; - SoundSpriteNum = -1; - - //MONO_PRINT("TmpVocArray playing a non-follow sound"); - } - } - // } // MoveSkip8 - - // Clean out any deleted sounds now - Delete3DSounds(); -} - -////////////////////////////////////////////////// -// Terminate the sounds list -////////////////////////////////////////////////// -void -Terminate3DSounds(void) -{ - VOC3D_INFOp vp; - - vp = voc3dstart; - - while (vp) - { - if (vp->handle > 0) - FX_StopSound(vp->handle); // Make sure to stop active sounds - vp->handle = 0; - vp->deleted = TRUE; - vp = vp->next; - } - - Delete3DSounds(); // Now delete all remaining sounds - ClearSoundLocks(); -} - -void -DumpSounds(void) -{ - VOC3D_INFOp vp; - - vp = voc3dstart; - - while (vp) - { - if (TEST(vp->flags,v3df_ambient)) - sprintf(ds,"vp->num=%d, vp->owner=%d, vp->vp->lock=%d",ambarray[vp->num].diginame,vp->owner,vp->vp->lock); - else - sprintf(ds,"vp->num=%d, vp->owner=%d, vp->vp->lock=%d",vp->num,vp->owner,vp->vp->lock); - DebugWriteString(ds); - if (vp->owner >= 0) - { - SPRITEp sp = &sprite[vp->owner]; - sprintf(ds,"sp->picnum=%d, sp->hitag=%d, sp->lotag=%d, sp->owner=%d\n",TrackerCast(sp->picnum), TrackerCast(sp->hitag), TrackerCast(sp->lotag), TrackerCast(sp->owner)); - DebugWriteString(ds); - } - vp = vp->next; - } -} - - -////////////////////////////////////////////////// -// Set owner to check when to kill looping sounds -// Must be called immediately after PlaySound call -// since this only assigns value to last sound -// on voc list -////////////////////////////////////////////////// -void -Set3DSoundOwner(short spritenum) -{ - VOC3D_INFOp p; - -// ASSERT(p->handle != -1); // Check for bogus sounds - - p = voc3dend; - if (!p) return; - - // Queue up sounds with ambient flag even if they didn't play right away! - if (p->handle != -1 || TEST(p->flags,v3df_ambient)) - { - p->owner = spritenum; - } - else - { - p->deleted = TRUE; - p->flags = v3df_kill; - } -} - -////////////////////////////////////////////////// -// Play a sound using special sprite setup -////////////////////////////////////////////////// -void -PlaySpriteSound(short spritenum, int attrib_ndx, Voc3D_Flags flags) -{ - SPRITEp sp = &sprite[spritenum]; - USERp u = User[spritenum]; - - ASSERT(u); - -// //DSPRINTF(ds,"index = %d, digi num = %d\n",attrib_ndx,u->Attrib->Sounds[attrib_ndx]); -// MONO_PRINT(ds); - PlaySound(u->Attrib->Sounds[attrib_ndx], &sp->x, &sp->y, &sp->z, flags); -} END_SW_NS diff --git a/source/sw/src/sounds.h b/source/sw/src/sounds.h index e5b4af630..eab266b92 100644 --- a/source/sw/src/sounds.h +++ b/source/sw/src/sounds.h @@ -57,22 +57,21 @@ enum v3df_intermit = 32, // 1 = Intermittant sound v3df_init = 64, // 1 = First pass of sound, don't play it. // This is mainly used for intermittent sounds - v3df_nolookup = 128 // don't use ambient table lookup + v3df_nolookup = 128, // don't use ambient table lookup }; typedef int Voc3D_Flags; struct VOCstruct; typedef struct VOCstruct VOC_INFO, *VOC_INFOp; +#if 0 struct VOC3Dstruct; typedef struct VOC3Dstruct VOC3D_INFO, *VOC3D_INFOp; +#endif struct ambientstruct; typedef struct ambientstruct AMB_INFO, *AMB_INFOp; -extern VOC3D_INFOp voc3dstart; -extern VOC3D_INFOp voc3dend; - -void DoUpdateSounds3D(void); +void DoUpdateSounds(void); void Terminate3DSounds(void); void Set3DSoundOwner(short spritenum); @@ -80,7 +79,7 @@ void PlaySpriteSound(short spritenum, int attrib_ndx, Voc3D_Flags flags); void DeleteNoSoundOwner(short spritenum); void DeleteNoFollowSoundOwner(short spritenum); -SWBOOL CacheSound(int num, int type); +inline SWBOOL CacheSound(int num, int type) { return false; } void COVER_SetReverb(int amt); void UnInitSound(void); void InitFX(void); @@ -143,13 +142,14 @@ struct VOCstruct int16_t voc_num; // Backward reference to parent sound int voc_distance; // Sound's distance effectiveness Voc_Flags voc_flags; // Various allowable flag settings for voc - uint8_t lock; // locking byte for caching + uint16_t lock; // locking byte for caching uint8_t playing; // number of this type of sound currently playing }; // JIMSOUND3D(tm) variables section ////////////////////////////////////////// +#if 0 struct VOC3Dstruct { VOC_INFOp vp; // Pointer to the sound @@ -174,6 +174,7 @@ struct VOC3Dstruct SWBOOL deleted; // Has sound been marked for deletion? SWBOOL FX_Ok; // Did this sound play ok? }; +#endif extern VOC_INFO voc[]; diff --git a/source/sw/src/sprite.cpp b/source/sw/src/sprite.cpp index 2264b0838..b57f5d29c 100644 --- a/source/sw/src/sprite.cpp +++ b/source/sw/src/sprite.cpp @@ -817,6 +817,8 @@ KillSprite(int16_t SpriteNum) void ChangeState(short SpriteNum, STATEp statep) { USERp u = User[SpriteNum]; + if (u == nullptr) + return; u->Tics = 0; u->State = u->StateStart = statep; @@ -5504,7 +5506,7 @@ void ChoosePlayerGetSound(PLAYERp pp) choose_snd = STD_RANDOM_RANGE((MAX_GETSOUNDS-1)<<8)>>8; - PlayerSound(PlayerGetItemVocs[choose_snd],&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(PlayerGetItemVocs[choose_snd], v3df_follow|v3df_dontpan,pp); } SWBOOL CanGetWeapon(PLAYERp pp, short SpriteNum, int WPN) @@ -5584,7 +5586,7 @@ DoGet(short SpriteNum) u->WaitTics -= ACTORMOVETICS * 2; if (u->WaitTics <= 0) { - PlaySound(DIGI_ITEM_SPAWN, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_ITEM_SPAWN, sp, v3df_none); DoSpawnItemTeleporterEffect(sp); RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); } @@ -5674,7 +5676,7 @@ KeyMain: pp->HasKey[key_num] = TRUE; SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_KEY, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_KEY, sp, v3df_dontpan); PlayerUpdateKeys(pp); // don't kill keys in coop @@ -5704,7 +5706,7 @@ KeyMain: } SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_BIGITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_BIGITEM, sp, v3df_dontpan); // override for respawn mode if (gNet.MultiGameType == MULTI_GAME_COMMBAT && gNet.NoRespawn) @@ -5739,7 +5741,7 @@ KeyMain: SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); // override for respawn mode if (gNet.MultiGameType == MULTI_GAME_COMMBAT && gNet.NoRespawn) @@ -5769,7 +5771,7 @@ KeyMain: SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_BIGITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_BIGITEM, sp, v3df_dontpan); // override for respawn mode if (gNet.MultiGameType == MULTI_GAME_COMMBAT && gNet.NoRespawn) @@ -5795,7 +5797,7 @@ KeyMain: PlayerUpdateInventory(pp, INVENTORY_MEDKIT); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); // override for respawn mode if (gNet.MultiGameType == MULTI_GAME_COMMBAT && gNet.NoRespawn) @@ -5818,7 +5820,7 @@ KeyMain: PlayerUpdateInventory(pp, INVENTORY_CHEMBOMB); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); } break; @@ -5833,7 +5835,7 @@ KeyMain: PlayerUpdateInventory(pp, INVENTORY_FLASHBOMB); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); } break; @@ -5850,7 +5852,7 @@ KeyMain: PlayerUpdateInventory(pp, INVENTORY_CALTROPS); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); } break; @@ -5864,7 +5866,7 @@ KeyMain: PlayerUpdateInventory(pp, INVENTORY_NIGHT_VISION); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); } break; @@ -5877,7 +5879,7 @@ KeyMain: PlayerUpdateInventory(pp, INVENTORY_REPAIR_KIT); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); // don't kill repair kit in coop if (gNet.MultiGameType == MULTI_GAME_COOPERATIVE) @@ -5894,7 +5896,7 @@ KeyMain: pp->InventoryAmount[INVENTORY_ENVIRON_SUIT] = 1; PlayerUpdateInventory(pp, INVENTORY_ENVIRON_SUIT); if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); } break; @@ -5908,7 +5910,7 @@ KeyMain: PlayerUpdateInventory(pp, INVENTORY_CLOAK); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); } break; @@ -5929,7 +5931,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_STAR, DamageData[WPN_STAR].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetWeapon(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_STAR))) break; @@ -5956,7 +5958,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_MINE, DamageData[WPN_MINE].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); ChoosePlayerGetSound(pp); KillGetWeapon(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_MINE))) @@ -5986,7 +5988,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_UZI, DamageData[WPN_UZI].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetWeapon(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_UZI)) && TEST(pp->Flags, PF_TWO_UZI)) @@ -5998,7 +6000,7 @@ KeyMain: SET(pp->Flags, PF_TWO_UZI); pp->WpnUziType = 0; // Let it come up if (pp == Player+myconnectindex) - PlayerSound(DIGI_DOUBLEUZI, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_follow, pp); + PlayerSound(DIGI_DOUBLEUZI, v3df_dontpan|v3df_follow, pp); } else { @@ -6023,7 +6025,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_UZI, DamageData[WPN_UZI].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetAmmo(SpriteNum); break; @@ -6042,7 +6044,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_MICRO, DamageData[WPN_MICRO].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); ChoosePlayerGetSound(pp); KillGetWeapon(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_MICRO))) @@ -6064,7 +6066,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_MICRO, DamageData[WPN_MICRO].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetAmmo(SpriteNum); break; @@ -6076,10 +6078,9 @@ KeyMain: pp->WpnRocketNuke = DamageData[DMG_NUCLEAR_EXP].weapon_pickup; SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); if (STD_RANDOM_RANGE(1000) > 800 && pp == Player+myconnectindex) - PlayerSound(DIGI_ILIKENUKES, &pp->posx, &pp->posy, &pp->posz, - v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_ILIKENUKES, v3df_dontpan|v3df_doppler|v3df_follow,pp); if (pp->CurWpn == pp->Wpn[WPN_MICRO]) { if (pp->WpnRocketType != 2) @@ -6110,11 +6111,10 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_GRENADE, DamageData[WPN_GRENADE].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); //ChoosePlayerGetSound(pp); if (STD_RANDOM_RANGE(1000) > 800 && pp == Player+myconnectindex) - PlayerSound(DIGI_LIKEBIGWEAPONS, &pp->posx, &pp->posy, &pp->posz, - v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_LIKEBIGWEAPONS, v3df_dontpan|v3df_doppler|v3df_follow,pp); KillGetWeapon(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_GRENADE))) break; @@ -6135,7 +6135,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_GRENADE, DamageData[WPN_GRENADE].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetAmmo(SpriteNum); break; @@ -6143,7 +6143,7 @@ KeyMain: case ICON_ROCKET: pp->WpnAmmo[WPN_ROCKET] += 15; if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_ROCKET))) break; @@ -6160,7 +6160,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_ROCKET, 20); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); break; #endif @@ -6180,15 +6180,13 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_RAIL, DamageData[WPN_RAIL].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); if (pp == Player+myconnectindex) { if (STD_RANDOM_RANGE(1000) > 700) - PlayerSound(DIGI_LIKEBIGWEAPONS, &pp->posx, &pp->posy, &pp->posz, - v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_LIKEBIGWEAPONS, v3df_dontpan|v3df_doppler|v3df_follow,pp); else - PlayerSound(DIGI_GOTRAILGUN, &pp->posx, &pp->posy, &pp->posz, - v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_GOTRAILGUN, v3df_dontpan|v3df_doppler|v3df_follow,pp); } //ChoosePlayerGetSound(pp); KillGetWeapon(SpriteNum); @@ -6213,7 +6211,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_RAIL, DamageData[WPN_RAIL].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetAmmo(SpriteNum); break; @@ -6231,7 +6229,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_SHOTGUN, DamageData[WPN_SHOTGUN].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); ChoosePlayerGetSound(pp); KillGetWeapon(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_SHOTGUN))) @@ -6253,7 +6251,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_SHOTGUN, DamageData[WPN_SHOTGUN].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetAmmo(SpriteNum); break; @@ -6266,7 +6264,7 @@ KeyMain: pp->WpnShotgunAuto = 50; SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); if (pp->CurWpn == pp->Wpn[WPN_SHOTGUN]) { @@ -6297,11 +6295,10 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_HOTHEAD, DamageData[WPN_HOTHEAD].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); //ChoosePlayerGetSound(pp); if (STD_RANDOM_RANGE(1000) > 800 && pp == Player+myconnectindex) - PlayerSound(DIGI_LIKEBIGWEAPONS, &pp->posx, &pp->posy, &pp->posz, - v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_LIKEBIGWEAPONS, v3df_dontpan|v3df_doppler|v3df_follow,pp); KillGetWeapon(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_HOTHEAD))) break; @@ -6324,7 +6321,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_HOTHEAD, DamageData[WPN_HOTHEAD].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetAmmo(SpriteNum); break; @@ -6343,11 +6340,10 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_HEART, DamageData[WPN_HEART].weapon_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); //ChoosePlayerGetSound(pp); if (STD_RANDOM_RANGE(1000) > 800 && pp == Player+myconnectindex) - PlayerSound(DIGI_LIKEBIGWEAPONS, &pp->posx, &pp->posy, &pp->posz, - v3df_dontpan|v3df_doppler|v3df_follow,pp); + PlayerSound(DIGI_LIKEBIGWEAPONS, v3df_dontpan|v3df_doppler|v3df_follow,pp); KillGetWeapon(SpriteNum); if (TEST(pp->WpnFlags, BIT(WPN_HEART))) break; @@ -6372,7 +6368,7 @@ KeyMain: PlayerUpdateAmmo(pp, WPN_HEART, DamageData[WPN_HEART].ammo_pickup); SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGetAmmo(SpriteNum); break; @@ -6398,7 +6394,7 @@ KeyMain: MNU_MeasureString(SpellName[sp->lotag], &w, &h); PutStringTimer(pp, TEXT_TEST_COL(w), TEXT_SPELL_INFO_LINE, SpellName[sp->lotag], TEXT_TEST_TIME); if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); break; } @@ -6413,7 +6409,7 @@ KeyMain: pp->WpnRocketHeat = DamageData[DMG_NUCLEAR_EXP].ammo_pickup; SetFadeAmt(pp,ITEMFLASHAMT,ITEMFLASHCLR); // Flash blue on item pickup if (pp == Player+myconnectindex) - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); KillGet(SpriteNum); if (pp->CurWpn == pp->Wpn[WPN_MICRO]) @@ -6436,7 +6432,7 @@ KeyMain: case ICON_FLAG: if (sp->pal == sprite[pp->PlayerSprite].pal) break; // Can't pick up your own flag! - PlaySound(DIGI_ITEM, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_ITEM, sp, v3df_dontpan); if (sp->hitag == TAG_NORESPAWN_FLAG) New = SpawnSprite(STAT_ITEM, ICON_FLAG, s_CarryFlagNoDet, sp->sectnum, @@ -7207,7 +7203,7 @@ void MissileWarpType(SPRITEp sp, SPRITEp sp_warp) case 1: break; default: - PlaySound(DIGI_ITEM_SPAWN, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_ITEM_SPAWN, sp, v3df_none); //DoSpawnTeleporterEffectPlace(sp); DoSpawnItemTeleporterEffect(sp); break; @@ -7221,7 +7217,7 @@ void ActorWarpType(SPRITEp sp, SPRITEp sp_warp) case 1: break; default: - PlaySound(DIGI_ITEM_SPAWN, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_ITEM_SPAWN, sp, v3df_none); DoSpawnTeleporterEffectPlace(sp); break; } diff --git a/source/sw/src/sumo.cpp b/source/sw/src/sumo.cpp index 565c71312..7427cd95a 100644 --- a/source/sw/src/sumo.cpp +++ b/source/sw/src/sumo.cpp @@ -726,7 +726,7 @@ int InitSumoCharge(short SpriteNum) USERp u = User[SpriteNum]; if (RANDOM_P2(1024) > 950) - PlaySound(DIGI_SUMOALERT, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_SUMOALERT, sp, v3df_follow); DoActorSetSpeed(SpriteNum, FAST_SPEED); @@ -754,7 +754,7 @@ int InitSumoFart(short SpriteNum) USERp u = User[SpriteNum]; extern int InitSumoNapalm(short SpriteNum); - PlaySound(DIGI_SUMOFART, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_SUMOFART, sp, v3df_follow); InitChemBomb(SpriteNum); @@ -770,7 +770,7 @@ int InitSumoStomp(short SpriteNum) USERp u = User[SpriteNum]; extern int InitSumoStompAttack(short SpriteNum); - PlaySound(DIGI_SUMOSTOMP, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SUMOSTOMP, sp, v3df_none); SetSumoQuake(SpriteNum); InitSumoStompAttack(SpriteNum); @@ -795,7 +795,7 @@ int DoSumoDeathMelt(short SpriteNum) SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; - PlaySound(DIGI_SUMOFART, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_SUMOFART, sp, v3df_follow); u->ID = SUMO_RUN_R0; InitChemBomb(SpriteNum); diff --git a/source/sw/src/swconfig.cpp b/source/sw/src/swconfig.cpp index c01bf1862..b182c99d8 100644 --- a/source/sw/src/swconfig.cpp +++ b/source/sw/src/swconfig.cpp @@ -33,7 +33,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms //#include "settings.h" #include "mytypes.h" -#include "fx_man.h" #include "gamedefs.h" #include "common_game.h" #include "config.h" diff --git a/source/sw/src/track.cpp b/source/sw/src/track.cpp index 68935f81c..69390e316 100644 --- a/source/sw/src/track.cpp +++ b/source/sw/src/track.cpp @@ -642,7 +642,7 @@ TrackSetup(void) { int i, nexti; auto const sp = (uspritetype const *)&sprite[headspritestat[STAT_TRACK+ndx]]; - buildprintf("WARNING: Did not find first point of Track Number %d, x %d, y %d", ndx, sp->x, sp->y); + buildprintf("WARNING: Did not find first point of Track Number %d, x %d, y %d\n", ndx, sp->x, sp->y); for (i=headspritestat[STAT_TRACK+ndx]; i>=0; i=nexti) { // neuter the track's sprite list @@ -1598,6 +1598,12 @@ PlaceActorsOnTracks(void) NextActorTrackPoint(i); + if (Track[u->track].NumPoints == 0) + { + buildprintf("WARNING: Sprite %d (%d, %d) placed on track %d with no points!\n", i, TrackerCast(sp->x), TrackerCast(sp->y), u->track); + continue; + } + // check angle in the "forward" direction sp->ang = getangle((tpoint + u->point)->x - sp->x, (tpoint + u->point)->y - sp->y); } diff --git a/source/sw/src/weapon.cpp b/source/sw/src/weapon.cpp index c5f255cf8..3f273ba60 100644 --- a/source/sw/src/weapon.cpp +++ b/source/sw/src/weapon.cpp @@ -3284,7 +3284,7 @@ AutoShrap: return FALSE; case SHRAP_GLASS: - PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKGLASS,parent,v3df_dontpan|v3df_doppler); p = GlassShrap; //BreakShrapSetup(GlassShrap, sizeof(GlassShrap), CustomShrap, shrap_amt); if (shrap_amt) @@ -3300,7 +3300,7 @@ AutoShrap: case SHRAP_GENERIC: case SHRAP_STONE: - PlaySound(DIGI_BREAKSTONES,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKSTONES,parent,v3df_dontpan|v3df_doppler); p = StoneShrap; if (shrap_amt) { @@ -3314,7 +3314,7 @@ AutoShrap: break; case SHRAP_WOOD: - PlaySound(DIGI_BREAKINGWOOD,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKINGWOOD,parent,v3df_dontpan|v3df_doppler); p = WoodShrap; if (shrap_amt) { @@ -3332,14 +3332,14 @@ AutoShrap: break; case SHRAP_GIBS: - PlaySound(DIGI_GIBS1,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_GIBS1,parent,v3df_dontpan|v3df_doppler); p = SmallGore; shrap_xsize = shrap_ysize = 34; shrap_bounce = FALSE; break; case SHRAP_TREE_BARK: - PlaySound(DIGI_BREAKINGWOOD,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKINGWOOD,parent,v3df_dontpan|v3df_doppler); p = WoodShrap; if (shrap_amt) { @@ -3365,7 +3365,7 @@ AutoShrap: break; case SHRAP_METAL: - PlaySound(DIGI_BREAKMETAL,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKMETAL,parent,v3df_dontpan|v3df_doppler); p = MetalShrap; if (shrap_amt) { @@ -3380,7 +3380,7 @@ AutoShrap: case SHRAP_COIN: - PlaySound(DIGI_COINS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_COINS,parent,v3df_dontpan|v3df_doppler); p = CoinShrap; if (shrap_amt) { @@ -3394,7 +3394,7 @@ AutoShrap: break; case SHRAP_METALMIX: - PlaySound(DIGI_BREAKMETAL,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKMETAL,parent,v3df_dontpan|v3df_doppler); p = MetalMix; if (shrap_amt) { @@ -3428,7 +3428,7 @@ AutoShrap: ep->xrepeat = ep->yrepeat = size + shrap_delta_size; #endif - //PlaySound(DIGI_BREAKMARBELS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + //PlaySound(DIGI_BREAKMARBELS,parent,v3df_dontpan|v3df_doppler); p = Marbels; if (shrap_amt) { @@ -3443,7 +3443,7 @@ AutoShrap: break; case SHRAP_WOODMIX: - PlaySound(DIGI_BREAKINGWOOD,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKINGWOOD,parent,v3df_dontpan|v3df_doppler); p = WoodMix; if (shrap_amt) { @@ -3457,7 +3457,7 @@ AutoShrap: break; case SHRAP_PAPERMIX: - PlaySound(DIGI_BREAKINGWOOD,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKINGWOOD,parent,v3df_dontpan|v3df_doppler); p = PaperMix; if (shrap_amt) { @@ -3533,42 +3533,42 @@ AutoShrap: break; case BREAK_BARREL: - PlaySound(DIGI_BREAKDEBRIS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKDEBRIS,parent,v3df_dontpan|v3df_doppler); p = WoodShrap; shrap_xsize = shrap_ysize = 24; shrap_bounce = TRUE; ChangeState(parent - sprite, s_BreakBarrel); break; case BREAK_LIGHT: - PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKGLASS,parent,v3df_dontpan|v3df_doppler); p = GlassShrap; shrap_xsize = shrap_ysize = 24; shrap_bounce = TRUE; ChangeState(parent - sprite, s_BreakLight); break; case BREAK_PEDISTAL: - PlaySound(DIGI_BREAKSTONES,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKSTONES,parent,v3df_dontpan|v3df_doppler); p = StoneShrap; shrap_xsize = shrap_ysize = 24; shrap_bounce = TRUE; ChangeState(parent - sprite, s_BreakPedistal); break; case BREAK_BOTTLE1: - PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKGLASS,parent,v3df_dontpan|v3df_doppler); p = GlassShrap; shrap_xsize = shrap_ysize = 8; shrap_bounce = TRUE; ChangeState(parent - sprite, s_BreakBottle1); break; case BREAK_BOTTLE2: - PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKGLASS,parent,v3df_dontpan|v3df_doppler); p = GlassShrap; shrap_xsize = shrap_ysize = 8; shrap_bounce = TRUE; ChangeState(parent - sprite, s_BreakBottle2); break; case BREAK_MUSHROOM: - PlaySound(DIGI_BREAKDEBRIS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKDEBRIS,parent,v3df_dontpan|v3df_doppler); p = StoneShrap; shrap_xsize = shrap_ysize = 4; shrap_bounce = TRUE; @@ -3600,7 +3600,7 @@ AutoShrap: shrap_xsize = shrap_ysize = 10; break; case LAVA_BOULDER: - PlaySound(DIGI_BREAKSTONES,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKSTONES,parent,v3df_dontpan|v3df_doppler); p = LavaBoulderShrap; shrap_owner = parent->owner; shrap_xsize = shrap_ysize = 24; @@ -3715,7 +3715,7 @@ AutoShrap: case PACHINKO3: case PACHINKO4: case 623: - PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BREAKGLASS,parent,v3df_dontpan|v3df_doppler); p = MetalShrap; shrap_xsize = shrap_ysize = 10; break; @@ -4606,8 +4606,8 @@ WeaponMoveHit(short SpriteNum) switch (hu->ID) { case TRASHCAN: - PlaySound(DIGI_TRASHLID, &sp->x, &sp->y, &sp->z, v3df_none); - PlaySound(DIGI_STARCLINK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_TRASHLID, sp, v3df_none); + PlaySound(DIGI_STARCLINK, sp, v3df_none); if (hu->WaitTics <= 0) { hu->WaitTics = SEC(2); @@ -4621,7 +4621,7 @@ WeaponMoveHit(short SpriteNum) case ZILLA_RUN_R0: case 623: { - PlaySound(DIGI_STARCLINK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STARCLINK, sp, v3df_none); } break; } @@ -4949,8 +4949,11 @@ SetSuicide(short SpriteNum) SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; - SET(u->Flags, SPR_SUICIDE); - u->RotNum = 0; + if (u != nullptr) + { + SET(u->Flags, SPR_SUICIDE); + u->RotNum = 0; + } ChangeState(SpriteNum, s_Suicide); #else // this will NOT work because @@ -5148,7 +5151,7 @@ ActorChooseDeath(short SpriteNum, short Weapon) PLAYERp pp = wu->PlayerP; if (pp && !TEST(pp->Flags, PF_DIVING)) // JBF: added null test pp->Bloody = TRUE; - PlaySound(DIGI_TOILETGIRLSCREAM, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_TOILETGIRLSCREAM, sp, v3df_none); } if (SpawnShrap(SpriteNum, Weapon)) SetSuicide(SpriteNum); @@ -5179,17 +5182,17 @@ ActorChooseDeath(short SpriteNum, short Weapon) choosesnd=STD_RANDOM_RANGE(6); if (choosesnd == 0) - PlayerSound(DIGI_KUNGFU,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_KUNGFU, v3df_follow|v3df_dontpan,pp); else if (choosesnd == 1) - PlayerSound(DIGI_PAYINGATTENTION,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_PAYINGATTENTION, v3df_follow|v3df_dontpan,pp); else if (choosesnd == 2) - PlayerSound(DIGI_EATTHIS,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_EATTHIS, v3df_follow|v3df_dontpan,pp); else if (choosesnd == 3) - PlayerSound(DIGI_TAUNTAI4,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_TAUNTAI4, v3df_follow|v3df_dontpan,pp); else if (choosesnd == 4) - PlayerSound(DIGI_TAUNTAI5,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_TAUNTAI5, v3df_follow|v3df_dontpan,pp); else if (choosesnd == 5) - PlayerSound(DIGI_HOWYOULIKEMOVE,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_HOWYOULIKEMOVE, v3df_follow|v3df_dontpan,pp); //PlayerSound(TauntAIVocs[choosesnd],&pp->posx, // &pp->posy,&pp->posy,v3df_dontpan|v3df_follow,pp); } @@ -5199,13 +5202,13 @@ ActorChooseDeath(short SpriteNum, short Weapon) choose_snd = STD_RANDOM_RANGE(1000); if (choose_snd > 750) - PlayerSound(DIGI_SWORDGOTU1,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_SWORDGOTU1, v3df_follow|v3df_dontpan,pp); else if (choose_snd > 575) - PlayerSound(DIGI_SWORDGOTU2,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_SWORDGOTU2, v3df_follow|v3df_dontpan,pp); else if (choose_snd > 250) - PlayerSound(DIGI_SWORDGOTU3,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_SWORDGOTU3, v3df_follow|v3df_dontpan,pp); else - PlayerSound(DIGI_CANBEONLYONE,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_CANBEONLYONE, v3df_follow|v3df_dontpan,pp); } if (!TEST(pp->Flags, PF_DIVING)) pp->Bloody = TRUE; @@ -5293,8 +5296,7 @@ ActorChooseDeath(short SpriteNum, short Weapon) choosesnd=STD_RANDOM_RANGE(MAX_TAUNTAI<<8)>>8; if (pp && pp == Player+myconnectindex) - PlayerSound(TauntAIVocs[choosesnd],&pp->posx, - &pp->posy,&pp->posy,v3df_dontpan|v3df_follow,pp); + PlayerSound(TauntAIVocs[choosesnd],v3df_dontpan|v3df_follow,pp); } } } @@ -5419,7 +5421,7 @@ ActorHealth(short SpriteNum, short amt) SET(u->Flags2, SPR2_DYING); // Only let it check this once! u->WaitTics = SEC(1) + SEC(RANDOM_RANGE(2)); u->Health = 60; - PlaySound(DIGI_NINJACHOKE,&sp->x,&sp->y,&sp->z,v3df_follow); + PlaySound(DIGI_NINJACHOKE, sp, v3df_follow); InitPlasmaFountain(NULL, sp); InitBloodSpray(SpriteNum,FALSE,105); sp->ang = NORM_ANGLE(getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y) + 1024); @@ -6012,8 +6014,7 @@ DoDamage(short SpriteNum, short Weapon) if (STD_RANDOM_RANGE(1024) > 512 && pp == Player+myconnectindex) { choosesnd=RANDOM_RANGE(MAX_TAUNTAI); - PlayerSound(TauntAIVocs[choosesnd],&pp->posx, - &pp->posy,&pp->posy,v3df_dontpan|v3df_follow,pp); + PlayerSound(TauntAIVocs[choosesnd],v3df_dontpan|v3df_follow,pp); } SpawnShrap(SpriteNum, Weapon); SetSuicide(SpriteNum); @@ -6079,7 +6080,7 @@ DoDamage(short SpriteNum, short Weapon) damage -= 5 - RANDOM_RANGE(10); break; } - PlaySound(DIGI_CGTHIGHBONE,&wp->x,&wp->y,&wp->z,v3df_follow|v3df_dontpan); + PlaySound(DIGI_CGTHIGHBONE,wp,v3df_follow|v3df_dontpan); } ////DSPRINTF(ds,"got here 3, %d",damage); @@ -6101,7 +6102,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerCheckDeath(u->PlayerP, Weapon); } if (u->PlayerP->Armor) - PlaySound(DIGI_ARMORHIT,&u->PlayerP->posx,&u->PlayerP->posy,&u->PlayerP->posz,v3df_dontpan|v3df_follow|v3df_doppler); + PlaySound(DIGI_ARMORHIT,u->PlayerP,v3df_dontpan|v3df_follow|v3df_doppler); } else { @@ -6147,7 +6148,7 @@ DoDamage(short SpriteNum, short Weapon) break; case HORNET_RUN_R0: - PlaySound(DIGI_HORNETSTING,&sp->x,&sp->y,&sp->z,v3df_follow|v3df_dontpan); + PlaySound(DIGI_HORNETSTING, sp, v3df_follow|v3df_dontpan); damage = GetDamage(SpriteNum, Weapon, DMG_HORNET_STING); if (u->sop_parent) { @@ -6224,8 +6225,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerUpdateHealth(u->PlayerP, damage); if (PlayerCheckDeath(u->PlayerP, Weapon)) { - PlaySound(DIGI_RIPPERHEARTOUT,&u->PlayerP->posx,&u->PlayerP->posy, - &u->PlayerP->posz,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RIPPERHEARTOUT,u->PlayerP,v3df_dontpan|v3df_doppler); DoRipperRipHeart(Weapon); } @@ -6259,8 +6259,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerUpdateHealth(u->PlayerP, damage); if (PlayerCheckDeath(u->PlayerP, Weapon)) { - PlaySound(DIGI_RIPPERHEARTOUT,&u->PlayerP->posx,&u->PlayerP->posy, - &u->PlayerP->posz,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RIPPERHEARTOUT,u->PlayerP,v3df_dontpan|v3df_doppler); DoRipper2RipHeart(Weapon); } @@ -6405,7 +6404,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerCheckDeath(u->PlayerP, Weapon); } if (u->PlayerP->Armor) - PlaySound(DIGI_ARMORHIT,&u->PlayerP->posx,&u->PlayerP->posy,&u->PlayerP->posz,v3df_dontpan|v3df_follow|v3df_doppler); + PlaySound(DIGI_ARMORHIT,u->PlayerP,v3df_dontpan|v3df_follow|v3df_doppler); } else { @@ -6439,7 +6438,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerCheckDeath(u->PlayerP, Weapon); } if (u->PlayerP->Armor) - PlaySound(DIGI_ARMORHIT,&u->PlayerP->posx,&u->PlayerP->posy,&u->PlayerP->posz,v3df_dontpan|v3df_follow|v3df_doppler); + PlaySound(DIGI_ARMORHIT,u->PlayerP,v3df_dontpan|v3df_follow|v3df_doppler); } else { @@ -6539,7 +6538,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerCheckDeath(u->PlayerP, Weapon); } if (u->PlayerP->Armor) - PlaySound(DIGI_ARMORHIT,&u->PlayerP->posx,&u->PlayerP->posy,&u->PlayerP->posz,v3df_dontpan|v3df_follow|v3df_doppler); + PlaySound(DIGI_ARMORHIT,u->PlayerP,v3df_dontpan|v3df_follow|v3df_doppler); } else { @@ -6588,7 +6587,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerCheckDeath(u->PlayerP, Weapon); } if (u->PlayerP->Armor) - PlaySound(DIGI_ARMORHIT,&u->PlayerP->posx,&u->PlayerP->posy,&u->PlayerP->posz,v3df_dontpan|v3df_follow|v3df_doppler); + PlaySound(DIGI_ARMORHIT,u->PlayerP,v3df_dontpan|v3df_follow|v3df_doppler); } else { @@ -6723,7 +6722,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerCheckDeath(u->PlayerP, Weapon); } if (u->PlayerP->Armor) - PlaySound(DIGI_ARMORHIT,&u->PlayerP->posx,&u->PlayerP->posy,&u->PlayerP->posz,v3df_dontpan|v3df_follow|v3df_doppler); + PlaySound(DIGI_ARMORHIT,u->PlayerP,v3df_dontpan|v3df_follow|v3df_doppler); } else { @@ -7263,7 +7262,7 @@ DoDamage(short SpriteNum, short Weapon) PlayerCheckDeath(u->PlayerP, Weapon); } if (u->PlayerP->Armor) - PlaySound(DIGI_ARMORHIT,&u->PlayerP->posx,&u->PlayerP->posy,&u->PlayerP->posz,v3df_dontpan|v3df_follow|v3df_doppler); + PlaySound(DIGI_ARMORHIT,u->PlayerP,v3df_dontpan|v3df_follow|v3df_doppler); } else { @@ -7320,7 +7319,7 @@ DoDamage(short SpriteNum, short Weapon) { PLAYERp pp = u->PlayerP; - PlayerSound(DIGI_GASHURT,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_follow|v3df_doppler,pp); + PlayerSound(DIGI_GASHURT, v3df_dontpan|v3df_follow|v3df_doppler,pp); PlayerUpdateHealth(u->PlayerP, damage-1000); PlayerCheckDeath(u->PlayerP, Weapon); } @@ -7388,7 +7387,7 @@ DoDamage(short SpriteNum, short Weapon) if (PlayerTakeDamage(u->PlayerP, Weapon)) { if (RANDOM_P2(1024<<4)>>4 < 800) - PlayerSound(DIGI_STEPONCALTROPS, &sp->x, &sp->y, &sp->z, v3df_follow|v3df_dontpan, u->PlayerP); + PlayerSound(DIGI_STEPONCALTROPS, v3df_follow|v3df_dontpan, u->PlayerP); PlayerUpdateHealth(u->PlayerP, damage); PlayerCheckDeath(u->PlayerP, Weapon); } @@ -7446,11 +7445,11 @@ DoDamage(short SpriteNum, short Weapon) if (u && u->PlayerP) { if (damage <= -40 && RANDOM_RANGE(1000) > 700) - PlayerSound(DIGI_SONOFABITCH, &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_follow, u->PlayerP); + PlayerSound(DIGI_SONOFABITCH, v3df_dontpan|v3df_follow, u->PlayerP); else if (damage <= -40 && RANDOM_RANGE(1000) > 700) - PlayerSound(DIGI_PAINFORWEAK, &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_follow, u->PlayerP); + PlayerSound(DIGI_PAINFORWEAK, v3df_dontpan|v3df_follow, u->PlayerP); else if (damage <= -10) - PlayerSound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_follow, u->PlayerP); + PlayerSound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], v3df_dontpan|v3df_follow, u->PlayerP); } return 0; @@ -8216,11 +8215,11 @@ DoStar(int16_t Weapon) { su = User[hit_sprite]; if (su && (su->ID == TRASHCAN || su->ID == ZILLA_RUN_R0)) // JBF: added null test - PlaySound(DIGI_STARCLINK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STARCLINK, sp, v3df_none); } if (TEST(u->ret, HIT_MASK) != HIT_SPRITE) // Don't clank on sprites - PlaySound(DIGI_STARCLINK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STARCLINK, sp, v3df_none); if (WeaponMoveHit(Weapon)) { @@ -8841,7 +8840,7 @@ DoCoolgFire(int16_t Weapon) { if (WeaponMoveHit(Weapon)) { - PlaySound(DIGI_CGMAGICHIT,&sp->x,&sp->y,&sp->z,v3df_follow); + PlaySound(DIGI_CGMAGICHIT, sp, v3df_follow); ChangeState(Weapon, s_CoolgFireDone); if (sp->owner >= 0 && User[sp->owner] && User[sp->owner]->ID != RIPPER_RUN_R0) // JBF: added range check SpawnDemonFist(Weapon); // Just a red magic circle flash @@ -9037,7 +9036,7 @@ DoGrenade(int16_t Weapon) short hit_sprite = -2; SPRITEp hsp; - PlaySound(DIGI_40MMBNCE, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_40MMBNCE, sp, v3df_dontpan); hit_sprite = NORM_SPRITE(u->ret); hsp = &sprite[hit_sprite]; @@ -9089,7 +9088,7 @@ DoGrenade(int16_t Weapon) break; } - PlaySound(DIGI_40MMBNCE, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_40MMBNCE, sp, v3df_dontpan); nw = wall[hit_wall].point2; wall_ang = NORM_ANGLE(getangle(wall[nw].x - wph->x, wall[nw].y - wph->y)+512); @@ -9168,7 +9167,7 @@ DoGrenade(int16_t Weapon) u->zchange = -u->zchange; ScaleSpriteVector(Weapon, 40000); // 18000 u->zchange /= 4; - PlaySound(DIGI_40MMBNCE, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_40MMBNCE, sp, v3df_dontpan); } else { @@ -9191,7 +9190,7 @@ DoGrenade(int16_t Weapon) { u->zchange = -u->zchange; ScaleSpriteVector(Weapon, 22000); - PlaySound(DIGI_40MMBNCE, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_40MMBNCE, sp, v3df_dontpan); } } break; @@ -9277,7 +9276,7 @@ DoVulcanBoulder(int16_t Weapon) short hit_sprite = -2; SPRITEp hsp; -// PlaySound(DIGI_DHCLUNK, &sp->x, &sp->y, &sp->z, v3df_dontpan); +// PlaySound(DIGI_DHCLUNK, sp, v3df_dontpan); hit_sprite = NORM_SPRITE(u->ret); hsp = &sprite[hit_sprite]; @@ -9315,7 +9314,7 @@ DoVulcanBoulder(int16_t Weapon) break; } -// PlaySound(DIGI_DHCLUNK, &sp->x, &sp->y, &sp->z, v3df_dontpan); +// PlaySound(DIGI_DHCLUNK, sp, v3df_dontpan); nw = wall[hit_wall].point2; wall_ang = NORM_ANGLE(getangle(wall[nw].x - wph->x, wall[nw].y - wph->y)+512); @@ -9517,7 +9516,7 @@ DoMineStuck(int16_t Weapon) { if ((u->Counter2++) > 30) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->WaitTics = 32767; // Keep reseting tics to make it stay forever u->Counter2 = 0; } @@ -9549,56 +9548,56 @@ DoMineStuck(int16_t Weapon) case 0: if (u->WaitTics < SEC(45)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 1: if (u->WaitTics < SEC(38)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 2: if (u->WaitTics < SEC(30)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 3: if (u->WaitTics < SEC(20)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 4: if (u->WaitTics < SEC(15)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 5: if (u->WaitTics < SEC(12)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 6: if (u->WaitTics < SEC(10)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; case 7: if (u->WaitTics < SEC(8)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2++; } break; @@ -9606,7 +9605,7 @@ DoMineStuck(int16_t Weapon) case 30: if (u->WaitTics < SEC(6)) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); u->Counter2 = MINE_DETONATE_STATE; } break; @@ -9614,14 +9613,14 @@ DoMineStuck(int16_t Weapon) // if (u->WaitTics < SEC(5)) // { // start frantic beeping -// PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); +// PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); // u->Counter2++; // } // break; case MINE_DETONATE_STATE: if (u->WaitTics < 0) { - PlaySound(DIGI_MINEBEEP, &sp->x, &sp->y, &sp->z, v3df_dontpan); + PlaySound(DIGI_MINEBEEP, sp, v3df_dontpan); SpawnMineExp(Weapon); KillSprite(Weapon); return FALSE; @@ -9720,13 +9719,13 @@ DoMine(int16_t Weapon) pp = uo->PlayerP; if (RANDOM_RANGE(1000) > 800) - PlayerSound(DIGI_STICKYGOTU1,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_STICKYGOTU1, v3df_follow|v3df_dontpan,pp); else if (RANDOM_RANGE(1000) > 800) - PlayerSound(DIGI_STICKYGOTU2,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_STICKYGOTU2, v3df_follow|v3df_dontpan,pp); else if (RANDOM_RANGE(1000) > 800) - PlayerSound(DIGI_STICKYGOTU3,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_STICKYGOTU3, v3df_follow|v3df_dontpan,pp); else if (RANDOM_RANGE(1000) > 800) - PlayerSound(DIGI_STICKYGOTU4,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_STICKYGOTU4, v3df_follow|v3df_dontpan,pp); } } } @@ -10282,7 +10281,7 @@ DoRocket(int16_t Weapon) DISTANCE(sp->x, sp->y, u->tgt_sp->x, u->tgt_sp->y, dist, a, b, c); u->FlagOwner = dist>>6; // Special warn sound attached to each seeker spawned - PlaySound(DIGI_MINEBEEP,&sp->x,&sp->y,&sp->z,v3df_follow); + PlaySound(DIGI_MINEBEEP, sp, v3df_follow); } if (TEST(u->Flags, SPR_FIND_PLAYER)) @@ -10766,7 +10765,7 @@ int SpawnCoolieExp(short SpriteNum) nx = sp->x + MOVEx(64, sp->ang+1024); ny = sp->y + MOVEy(64, sp->ang+1024); - PlaySound(DIGI_COOLIEEXPLODE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_COOLIEEXPLODE, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, BOLT_EXP, s_BoltExp, sp->sectnum, nx, ny, zh, sp->ang, 0); @@ -10802,7 +10801,7 @@ SpawnBasicExp(int16_t Weapon) if (TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_MEDIUMEXP, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_MEDIUMEXP, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, BASIC_EXP, s_BasicExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -10959,7 +10958,7 @@ SpawnFireballFlames(int16_t SpriteNum, int16_t enemy) DoBeginJump(New); } - PlaySound(DIGI_FIRE1,&np->x,&np->y,&np->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_FIRE1,np,v3df_dontpan|v3df_doppler); Set3DSoundOwner(New); return New; @@ -11001,7 +11000,7 @@ SpawnBreakFlames(int16_t SpriteNum) nu->jump_speed = 0; DoBeginJump(New); - PlaySound(DIGI_FIRE1,&np->x,&np->y,&np->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_FIRE1,np,v3df_dontpan|v3df_doppler); Set3DSoundOwner(New); return New; @@ -11051,7 +11050,7 @@ SpawnBreakStaticFlames(int16_t SpriteNum) //nu->jump_speed = 0; //DoBeginJump(New); - PlaySound(DIGI_FIRE1,&np->x,&np->y,&np->z,v3df_dontpan|v3df_doppler); + PlaySound(DIGI_FIRE1,np,v3df_dontpan|v3df_doppler); Set3DSoundOwner(New); return New; @@ -11072,7 +11071,7 @@ SpawnFireballExp(int16_t Weapon) if (TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_SMALLEXP, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SMALLEXP, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, FIREBALL_EXP, s_FireballExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -11115,7 +11114,7 @@ SpawnGoroFireballExp(int16_t Weapon) if (TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_MEDIUMEXP, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_MEDIUMEXP, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, 0, s_FireballExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -11154,7 +11153,7 @@ SpawnBoltExp(int16_t Weapon) if (u && TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_BOLTEXPLODE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_BOLTEXPLODE, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, BOLT_EXP, s_BoltExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -11196,7 +11195,7 @@ SpawnBunnyExp(int16_t Weapon) if (u && TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_BUNNYDIE3, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_BUNNYDIE3, sp, v3df_none); u->ID = BOLT_EXP; // Change id InitBloodSpray(Weapon,TRUE,-1); @@ -11221,7 +11220,7 @@ SpawnTankShellExp(int16_t Weapon) if (u && TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_BOLTEXPLODE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_BOLTEXPLODE, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, TANK_SHELL_EXP, s_TankShellExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -11310,7 +11309,7 @@ SpawnNuclearExp(int16_t Weapon) if (u && TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_NUCLEAREXP, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler); + PlaySound(DIGI_NUCLEAREXP, sp, v3df_dontpan | v3df_doppler); if (sp->owner) { @@ -11318,11 +11317,11 @@ SpawnNuclearExp(int16_t Weapon) rnd_rng = RANDOM_RANGE(1000); if (rnd_rng > 990) - PlayerSound(DIGI_LIKEHIROSHIMA,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_LIKEHIROSHIMA, v3df_follow|v3df_dontpan,pp); else if (rnd_rng > 980) - PlayerSound(DIGI_LIKENAGASAKI,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_LIKENAGASAKI, v3df_follow|v3df_dontpan,pp); else if (rnd_rng > 970) - PlayerSound(DIGI_LIKEPEARL,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_LIKEPEARL, v3df_follow|v3df_dontpan,pp); } // Spawn big mushroom cloud @@ -11448,7 +11447,7 @@ SpawnMicroExp(int16_t Weapon) if (u && TEST(u->Flags, SPR_SUICIDE)) return -1; -// PlaySound(DIGI_MISSLEXP, &sp->x, &sp->y, &sp->z, v3df_none); +// PlaySound(DIGI_MISSLEXP, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, MICRO_EXP, s_MicroExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -11668,14 +11667,14 @@ SpawnGrenadeExp(int16_t Weapon) if (u && TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_30MMEXPLODE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_30MMEXPLODE, sp, v3df_none); if (RANDOM_RANGE(1000) > 990) { if (sp->owner >= 0 && User[sp->owner] && User[sp->owner]->PlayerP) { PLAYERp pp = User[sp->owner]->PlayerP; - PlayerSound(DIGI_LIKEFIREWORKS,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_LIKEFIREWORKS, v3df_follow|v3df_dontpan,pp); } } @@ -11793,7 +11792,7 @@ SpawnMineExp(int16_t Weapon) change_sprite_stat(Weapon, STAT_MISSILE); - PlaySound(DIGI_MINEBLOW, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_MINEBLOW, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, MINE_EXP, s_MineExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -11919,7 +11918,7 @@ SpawnSectorExp(int16_t Weapon) if (TEST(u->Flags, SPR_SUICIDE)) return -1; - PlaySound(DIGI_30MMEXPLODE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_30MMEXPLODE, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, GRENADE_EXP, s_SectorExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -11951,7 +11950,7 @@ SpawnLargeExp(int16_t Weapon) USERp eu; short explosion; - PlaySound(DIGI_30MMEXPLODE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_30MMEXPLODE, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, GRENADE_EXP, s_SectorExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -11997,7 +11996,7 @@ SpawnMeteorExp(int16_t Weapon) } else { - PlaySound(DIGI_MEDIUMEXP, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_MEDIUMEXP, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, METEOR_EXP, s_MeteorExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); } @@ -12036,7 +12035,7 @@ SpawnLittleExp(int16_t Weapon) USERp eu; short explosion; - PlaySound(DIGI_HEADSHOTHIT, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_HEADSHOTHIT, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, BOLT_EXP, s_SectorExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); exp = &sprite[explosion]; @@ -12335,7 +12334,7 @@ DoNapalm(int16_t Weapon) { USERp eu; - PlaySound(DIGI_NAPPUFF, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_NAPPUFF, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, NAP_EXP, s_NapExp, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0); @@ -13026,7 +13025,7 @@ InitSpellRing(PLAYERp pp) ang_start = NORM_ANGLE(pp->pang - DIV2(2048)); if (!SW_SHAREWARE) - PlaySound(DIGI_RFWIZ, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_RFWIZ, pp, v3df_none); if (pp->cursectnum < 0) return; @@ -13209,7 +13208,7 @@ InitLavaThrow(short SpriteNum) int nx, ny, nz, dist, nang; short w; - //PlaySound(DIGI_NINJAROCKETATTACK, &sp->x, &sp->y, &sp->z, v3df_none); + //PlaySound(DIGI_NINJAROCKETATTACK, sp, v3df_none); // get angle to player and also face player when attacking sp->ang = nang = getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y); @@ -13350,7 +13349,7 @@ InitSerpRing(short SpriteNum) ang_start = NORM_ANGLE(sp->ang - DIV2(2048)); if (!SW_SHAREWARE) - PlaySound(DIGI_RFWIZ, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_RFWIZ, sp, v3df_none); for (missiles = 0, ang = ang_start; missiles < max_missiles; ang += ang_diff, missiles++) { @@ -13414,7 +13413,7 @@ InitSerpRing(short SpriteNum) ang_start = NORM_ANGLE(sp->ang - DIV2(2048)); - PlaySound(DIGI_SERPSUMMONHEADS, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SERPSUMMONHEADS, sp, v3df_none); for (missiles = 0, ang = ang_start; missiles < max_missiles; ang += ang_diff, missiles++) { @@ -13485,7 +13484,7 @@ InitSerpRing2(short SpriteNum) static int zpos[NUM_SERP_RING] = {Z(25), Z(130)}; - PlaySound(DIGI_SERPSUMMONHEADS, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SERPSUMMONHEADS, sp, v3df_none); for (i = 0; i < NUM_SERP_RING; i++) { @@ -13577,7 +13576,7 @@ InitSpellNapalm(PLAYERp pp) else PlayerUpdateAmmo(pp, WPN_HOTHEAD, -ammo); - PlaySound(DIGI_NAPFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_NAPFIRE, pp, v3df_none); if (pp->cursectnum < 0) return; @@ -13594,7 +13593,7 @@ InitSpellNapalm(PLAYERp pp) if (i==0) // Only attach sound to first projectile { - PlaySound(DIGI_NAPWIZ, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_NAPWIZ, sp, v3df_follow); Set3DSoundOwner(SpriteNum); } @@ -13667,7 +13666,7 @@ InitEnemyNapalm(short SpriteNum) {600 * 6, 400, -512}, }; - PlaySound(DIGI_NAPFIRE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_NAPFIRE, sp, v3df_none); for (i = 0; i < SIZ(mp); i++) { @@ -13680,7 +13679,7 @@ InitEnemyNapalm(short SpriteNum) wp->hitag = LUMINOUS; //Always full brightness if (i==0) // Only attach sound to first projectile { - PlaySound(DIGI_NAPWIZ, &wp->x, &wp->y, &wp->z, v3df_follow); + PlaySound(DIGI_NAPWIZ, wp, v3df_follow); Set3DSoundOwner(w); } @@ -13740,7 +13739,7 @@ InitSpellMirv(PLAYERp pp) short i; short oclipdist; - PlaySound(DIGI_MIRVFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_MIRVFIRE, pp, v3df_none); if (pp->cursectnum < 0) return 0; @@ -13751,7 +13750,7 @@ InitSpellMirv(PLAYERp pp) sp = &sprite[SpriteNum]; u = User[SpriteNum]; - PlaySound(DIGI_MIRVWIZ, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_MIRVWIZ, sp, v3df_follow); Set3DSoundOwner(SpriteNum); //sp->owner = pp->SpriteP - sprite; @@ -13792,7 +13791,7 @@ InitEnemyMirv(short SpriteNum) short oclipdist; int dist; - PlaySound(DIGI_MIRVFIRE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_MIRVFIRE, sp, v3df_none); w = SpawnSprite(STAT_MISSILE, MIRV_METEOR, s_Mirv, sp->sectnum, sp->x, sp->y, SPRITEp_TOS(sp) + DIV4(SPRITEp_SIZE_Z(sp)), sp->ang, MIRV_VELOCITY); @@ -13800,7 +13799,7 @@ InitEnemyMirv(short SpriteNum) wp = &sprite[w]; wu = User[w]; - PlaySound(DIGI_MIRVWIZ, &wp->x, &wp->y, &wp->z, v3df_follow); + PlaySound(DIGI_MIRVWIZ, wp, v3df_follow); Set3DSoundOwner(w); SetOwner(SpriteNum, w); @@ -13841,7 +13840,7 @@ InitSwordAttack(PLAYERp pp) int dist; short reach,face; - PlaySound(DIGI_SWORDSWOOSH, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_SWORDSWOOSH, pp, v3df_dontpan|v3df_doppler); if (TEST(pp->Flags, PF_DIVING)) { @@ -13940,7 +13939,7 @@ InitSwordAttack(PLAYERp pp) { case ZILLA_RUN_R0: SpawnSwordSparks(pp, hitinfo.sect, -1, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_SWORDCLANK, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); + PlaySound(DIGI_SWORDCLANK, &hitinfo.pos, v3df_none); break; case TRASHCAN: if (tu->WaitTics <= 0) @@ -13949,8 +13948,8 @@ InitSwordAttack(PLAYERp pp) ChangeState(hitinfo.sprite,s_TrashCanPain); } SpawnSwordSparks(pp, hitinfo.sect, -1, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_SWORDCLANK, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); - PlaySound(DIGI_TRASHLID, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SWORDCLANK, &hitinfo.pos, v3df_none); + PlaySound(DIGI_TRASHLID, sp, v3df_none); break; case PACHINKO1: case PACHINKO2: @@ -13958,7 +13957,7 @@ InitSwordAttack(PLAYERp pp) case PACHINKO4: case 623: SpawnSwordSparks(pp, hitinfo.sect, -1, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_SWORDCLANK, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); + PlaySound(DIGI_SWORDCLANK, &hitinfo.pos, v3df_none); break; } @@ -14002,7 +14001,7 @@ InitSwordAttack(PLAYERp pp) else { SpawnSwordSparks(pp, hitinfo.sect, hitinfo.wall, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_SWORDCLANK, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); + PlaySound(DIGI_SWORDCLANK, &hitinfo.pos, v3df_none); } } } @@ -14021,7 +14020,7 @@ InitFistAttack(PLAYERp pp) int dist; short reach,face; - PlaySound(DIGI_STAR, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_STAR, pp, v3df_dontpan|v3df_doppler); if (TEST(pp->Flags, PF_DIVING)) { @@ -14132,7 +14131,7 @@ InitFistAttack(PLAYERp pp) { case ZILLA_RUN_R0: SpawnSwordSparks(pp, hitinfo.sect, -1, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_ARMORHIT, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); + PlaySound(DIGI_ARMORHIT, &hitinfo.pos, v3df_none); break; case TRASHCAN: if (tu->WaitTics <= 0) @@ -14141,8 +14140,8 @@ InitFistAttack(PLAYERp pp) ChangeState(hitinfo.sprite,s_TrashCanPain); } SpawnSwordSparks(pp, hitinfo.sect, -1, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_ARMORHIT, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); - PlaySound(DIGI_TRASHLID, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_ARMORHIT, &hitinfo.pos, v3df_none); + PlaySound(DIGI_TRASHLID, sp, v3df_none); break; case PACHINKO1: case PACHINKO2: @@ -14150,7 +14149,7 @@ InitFistAttack(PLAYERp pp) case PACHINKO4: case 623: SpawnSwordSparks(pp, hitinfo.sect, -1, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_ARMORHIT, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); + PlaySound(DIGI_ARMORHIT, &hitinfo.pos, v3df_none); break; } @@ -14177,7 +14176,7 @@ InitFistAttack(PLAYERp pp) case 5063: case 4947: SpawnSwordSparks(pp, hitinfo.sect, -1, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_ARMORHIT, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); + PlaySound(DIGI_ARMORHIT, &hitinfo.pos, v3df_none); if (RANDOM_RANGE(1000) > 700) PlayerUpdateHealth(pp,1); // Give some health SET(hsp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); @@ -14207,7 +14206,7 @@ InitFistAttack(PLAYERp pp) else { SpawnSwordSparks(pp, hitinfo.sect, hitinfo.wall, hitinfo.pos.x, hitinfo.pos.y, hitinfo.pos.z, daang); - PlaySound(DIGI_ARMORHIT, &hitinfo.pos.x, &hitinfo.pos.y, &hitinfo.pos.z, v3df_none); + PlaySound(DIGI_ARMORHIT, &hitinfo.pos, v3df_none); if (PlayerTakeDamage(pp, -1)) { PlayerUpdateHealth(pp, -(RANDOM_RANGE(2<<8)>>8)); @@ -14242,7 +14241,7 @@ InitSumoNapalm(short SpriteNum) {0, 1100, 0}, }; - PlaySound(DIGI_NAPFIRE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_NAPFIRE, sp, v3df_none); ang = sp->ang; for (j=0; j<4; j++) @@ -14258,7 +14257,7 @@ InitSumoNapalm(short SpriteNum) wp->hitag = LUMINOUS; //Always full brightness if (i==0) // Only attach sound to first projectile { - PlaySound(DIGI_NAPWIZ, &wp->x, &wp->y, &wp->z, v3df_follow); + PlaySound(DIGI_NAPWIZ, wp, v3df_follow); Set3DSoundOwner(w); } @@ -14321,7 +14320,7 @@ InitSumoSkull(short SpriteNum) extern ATTRIBUTE SkullAttrib; - PlaySound(DIGI_SERPSUMMONHEADS, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SERPSUMMONHEADS, sp, v3df_none); New = SpawnSprite(STAT_ENEMY, SKULL_R0, &s_SkullWait[0][0], sp->sectnum, sp->x, sp->y, SPRITEp_MID(sp), sp->ang, 0); @@ -14375,7 +14374,7 @@ InitSumoStompAttack(short SpriteNum) short reach,face; - PlaySound(DIGI_30MMEXPLODE, &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_30MMEXPLODE, sp, v3df_dontpan|v3df_doppler); for (stat = 0; stat < SIZ(StatDamageList); stat++) { @@ -14427,7 +14426,7 @@ InitMiniSumoClap(short SpriteNum) { if (FAFcansee(u->tgt_sp->x,u->tgt_sp->y,SPRITEp_MID(u->tgt_sp),u->tgt_sp->sectnum,sp->x,sp->y,SPRITEp_MID(sp),sp->sectnum)) { - PlaySound(DIGI_CGTHIGHBONE,&sp->x,&sp->y,&sp->z,v3df_follow|v3df_dontpan); + PlaySound(DIGI_CGTHIGHBONE, sp, v3df_follow|v3df_dontpan); DoDamage(u->tgt_sp - sprite, SpriteNum); } } @@ -14436,7 +14435,7 @@ InitMiniSumoClap(short SpriteNum) { if (FAFcansee(u->tgt_sp->x,u->tgt_sp->y,SPRITEp_MID(u->tgt_sp),u->tgt_sp->sectnum,sp->x,sp->y,SPRITEp_MID(sp),sp->sectnum)) { - PlaySound(DIGI_30MMEXPLODE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_30MMEXPLODE, sp, v3df_none); SpawnFireballFlames(SpriteNum, u->tgt_sp - sprite); } } @@ -14756,7 +14755,7 @@ InitStar(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -3); - PlaySound(DIGI_STAR, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_STAR, pp, v3df_dontpan|v3df_doppler); if (pp->cursectnum < 0) return 0; @@ -15107,7 +15106,7 @@ InitShotgun(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -1); - PlaySound(DIGI_RIOTFIRE2, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RIOTFIRE2, pp, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; @@ -15230,7 +15229,7 @@ InitShotgun(PLAYERp pp) { extern STATE s_TrashCanPain[]; - PlaySound(DIGI_TRASHLID, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_TRASHLID, sp, v3df_none); if (hu->WaitTics <= 0) { hu->WaitTics = SEC(2); @@ -15282,7 +15281,7 @@ InitLaser(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -1); - PlaySound(DIGI_RIOTFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RIOTFIRE, pp, v3df_dontpan|v3df_doppler); if (pp->cursectnum < 0) return 0; @@ -15391,7 +15390,7 @@ InitRail(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -1); - PlaySound(DIGI_RAILFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RAILFIRE, pp, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; @@ -15480,7 +15479,7 @@ InitZillaRail(short SpriteNum) if (SW_SHAREWARE) return FALSE; // JBF: verify - PlaySound(DIGI_RAILFIRE, &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RAILFIRE, sp, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; @@ -15590,7 +15589,7 @@ InitRocket(PLAYERp pp) } } - PlaySound(DIGI_RIOTFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RIOTFIRE, pp, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; @@ -15714,7 +15713,7 @@ InitBunnyRocket(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -1); - PlaySound(DIGI_BUNNYATTACK, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BUNNYATTACK, pp, v3df_dontpan|v3df_doppler); if (pp->cursectnum < 0) return 0; @@ -15825,7 +15824,7 @@ InitNuke(PLAYERp pp) DoPlayerBeginRecoil(pp, ROCKET_RECOIL_AMT*12); - PlaySound(DIGI_RIOTFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RIOTFIRE, pp, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; @@ -15923,7 +15922,7 @@ InitEnemyNuke(short SpriteNum) int zvel; - PlaySound(DIGI_RIOTFIRE, &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RIOTFIRE, sp, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; @@ -16144,7 +16143,7 @@ InitRipperSlash(short SpriteNum) unsigned stat; int dist, a, b, c; - PlaySound(DIGI_RIPPER2ATTACK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_RIPPER2ATTACK, sp, v3df_none); for (stat = 0; stat < SIZ(StatDamageList); stat++) { @@ -16163,7 +16162,7 @@ InitRipperSlash(short SpriteNum) if (dist < CLOSE_RANGE_DIST_FUDGE(sp, hp, 600) && FACING_RANGE(hp, sp, 150)) { -// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], &sp->x, &sp->y, &sp->z, v3df_none); +// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], sp, v3df_none); DoDamage(i, SpriteNum); } } @@ -16182,7 +16181,7 @@ InitBunnySlash(short SpriteNum) unsigned stat; int dist, a, b, c; - PlaySound(DIGI_BUNNYATTACK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_BUNNYATTACK, sp, v3df_none); for (stat = 0; stat < SIZ(StatDamageList); stat++) { @@ -16217,7 +16216,7 @@ InitSerpSlash(short SpriteNum) unsigned stat; int dist, a, b, c; - PlaySound(DIGI_SERPSWORDATTACK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SERPSWORDATTACK, sp, v3df_none); for (stat = 0; stat < SIZ(StatDamageList); stat++) { @@ -16233,7 +16232,7 @@ InitSerpSlash(short SpriteNum) if (dist < CLOSE_RANGE_DIST_FUDGE(sp, hp, 800) && FACING_RANGE(hp, sp, 150)) { -// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], &sp->x, &sp->y, &sp->z, v3df_none); +// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], sp, v3df_none); DoDamage(i, SpriteNum); } } @@ -16313,7 +16312,7 @@ DoBladeDamage(short SpriteNum) if (WallSpriteInsideSprite(sp, hp)) { DoDamage(i, SpriteNum); -// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], &sp->x, &sp->y, &sp->z, v3df_none); +// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], sp, v3df_none); } } } @@ -16376,7 +16375,7 @@ InitCoolgBash(short SpriteNum) unsigned stat; int dist, a, b, c; - PlaySound(DIGI_CGTHIGHBONE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_CGTHIGHBONE, sp, v3df_none); for (stat = 0; stat < SIZ(StatDamageList); stat++) { @@ -16395,7 +16394,7 @@ InitCoolgBash(short SpriteNum) if (dist < CLOSE_RANGE_DIST_FUDGE(sp, hp, 600) && FACING_RANGE(hp, sp, 150)) { -// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], &sp->x, &sp->y, &sp->z, v3df_none); +// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], sp, v3df_none); DoDamage(i, SpriteNum); } } @@ -16414,7 +16413,7 @@ InitSkelSlash(short SpriteNum) unsigned stat; int dist, a, b, c; - PlaySound(DIGI_SPBLADE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SPBLADE, sp, v3df_none); for (stat = 0; stat < SIZ(StatDamageList); stat++) { @@ -16429,7 +16428,7 @@ InitSkelSlash(short SpriteNum) if (dist < CLOSE_RANGE_DIST_FUDGE(sp, hp, 600) && FACING_RANGE(hp, sp, 150)) { -// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], &sp->x, &sp->y, &sp->z, v3df_none); +// PlaySound(PlayerPainVocs[RANDOM_RANGE(MAX_PAIN)], sp, v3df_none); DoDamage(i, SpriteNum); } } @@ -16448,7 +16447,7 @@ InitGoroChop(short SpriteNum) unsigned stat; int dist, a, b, c; - PlaySound(DIGI_GRDSWINGAXE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_GRDSWINGAXE, sp, v3df_none); for (stat = 0; stat < SIZ(StatDamageList); stat++) { @@ -16463,7 +16462,7 @@ InitGoroChop(short SpriteNum) if (dist < CLOSE_RANGE_DIST_FUDGE(sp, hp, 700) && FACING_RANGE(hp, sp, 150)) { - PlaySound(DIGI_GRDAXEHIT, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_GRDAXEHIT, sp, v3df_none); DoDamage(i, SpriteNum); } } @@ -16523,7 +16522,7 @@ InitSerpSpell(short SpriteNum) //np->owner = SpriteNum; SetOwner(SpriteNum, New); np->shade = -40; - PlaySound(DIGI_SERPMAGICLAUNCH, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SERPMAGICLAUNCH, sp, v3df_none); nu->spal = np->pal = 27; // Bright Green np->xrepeat = 64; np->yrepeat = 64; @@ -16576,7 +16575,7 @@ SpawnDemonFist(int16_t Weapon) if (TEST(u->Flags, SPR_SUICIDE)) return -1; - //PlaySound(DIGI_ITEM_SPAWN, &sp->x, &sp->y, &sp->z, v3df_none); + //PlaySound(DIGI_ITEM_SPAWN, sp, v3df_none); explosion = SpawnSprite(STAT_MISSILE, 0, s_TeleportEffect, sp->sectnum, sp->x, sp->y, SPRITEp_MID(sp), sp->ang, 0); @@ -16621,7 +16620,7 @@ InitSerpMonstSpell(short SpriteNum) -10, 10 }; - PlaySound(DIGI_MISSLFIRE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_MISSLFIRE, sp, v3df_none); for (i = 0; i < 1; i++) { @@ -16689,7 +16688,7 @@ DoTeleRipper(short SpriteNum) USERp u = User[SpriteNum]; extern void Ripper2Hatch(short Weapon); - PlaySound(DIGI_ITEM_SPAWN,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_ITEM_SPAWN, sp, v3df_none); Ripper2Hatch(SpriteNum); return 0; @@ -16705,7 +16704,7 @@ InitEnemyRocket(short SpriteNum) short w; - PlaySound(DIGI_NINJARIOTATTACK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_NINJARIOTATTACK, sp, v3df_none); // get angle to player and also face player when attacking sp->ang = nang = getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y); @@ -16792,7 +16791,7 @@ InitEnemyRail(short SpriteNum) } } - PlaySound(DIGI_RAILFIRE, &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RAILFIRE, sp, v3df_dontpan|v3df_doppler); // get angle to player and also face player when attacking sp->ang = nang = getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y); @@ -16881,7 +16880,7 @@ InitZillaRocket(short SpriteNum) {1100 * 6, 400, -512}, }; - PlaySound(DIGI_NINJARIOTATTACK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_NINJARIOTATTACK, sp, v3df_none); // get angle to player and also face player when attacking sp->ang = nang = getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y); @@ -17000,7 +16999,7 @@ InitEnemyStar(short SpriteNum) USERp nu; short sn; - PlaySound(DIGI_STAR, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STAR, sp, v3df_none); for (i = 0; i < SIZ(dang); i++) { sn = SpawnSprite(STAT_MISSILE, STAR1, s_Star, sp->sectnum, wp->x, wp->y, wp->z, NORM_ANGLE(wp->ang + dang[i]), wp->xvel); @@ -17027,7 +17026,7 @@ InitEnemyStar(short SpriteNum) else #endif - PlaySound(DIGI_STAR, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STAR, sp, v3df_none); @@ -17094,7 +17093,7 @@ InitEnemyCrossbow(short SpriteNum) USERp nu; short sn; - PlaySound(DIGI_STAR, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STAR, sp, v3df_none); for (i = 0; i < SIZ(dang); i++) { sn = SpawnSprite(STAT_MISSILE, CROSSBOLT, s_CrossBolt, sp->sectnum, wp->x, wp->y, wp->z, NORM_ANGLE(wp->ang + dang[i]), wp->xvel); @@ -17121,7 +17120,7 @@ InitEnemyCrossbow(short SpriteNum) else #endif - PlaySound(DIGI_STAR, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STAR, sp, v3df_none); @@ -17137,7 +17136,7 @@ InitSkelSpell(short SpriteNum) int nx, ny, nz, dist, nang; short w; - PlaySound(DIGI_SPELEC, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SPELEC, sp, v3df_none); // get angle to player and also face player when attacking sp->ang = nang = NORM_ANGLE(getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y)); @@ -17197,7 +17196,7 @@ InitCoolgFire(short SpriteNum) // Spawn a shot // Inserting and setting up variables - PlaySound(DIGI_CGMAGIC, &sp->x, &sp->y, &sp->z, v3df_follow); + PlaySound(DIGI_CGMAGIC, sp, v3df_follow); w = SpawnSprite(STAT_MISSILE, COOLG_FIRE, s_CoolgFire, sp->sectnum, nx, ny, nz, u->tgt_sp->ang, COOLG_FIRE_VELOCITY); @@ -17221,7 +17220,7 @@ InitCoolgFire(short SpriteNum) else wu->spal = wp->pal = 25; // Bright Red - PlaySound(DIGI_MAGIC1, &wp->x, &wp->y, &wp->z, v3df_follow|v3df_doppler); + PlaySound(DIGI_MAGIC1, wp, v3df_follow|v3df_doppler); // find the distance to the target (player) dist = Distance(nx, ny, u->tgt_sp->x, u->tgt_sp->y); @@ -17257,7 +17256,7 @@ int DoCoolgDrip(short SpriteNum) sp->yrepeat = sp->xrepeat = 32; ChangeState(SpriteNum, s_GoreFloorSplash); if (u->spal == PALETTE_BLUE_LIGHTING) - PlaySound(DIGI_DRIP, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_DRIP, sp, v3df_none); } return 0; } @@ -17373,7 +17372,7 @@ InitEelFire(short SpriteNum) if (dist < CLOSE_RANGE_DIST_FUDGE(sp, hp, 600) && FACING_RANGE(hp, sp, 150)) { - PlaySound(DIGI_GIBS1, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_GIBS1, sp, v3df_none); DoDamage(i, SpriteNum); } else @@ -17392,7 +17391,7 @@ InitFireballTrap(short SpriteNum) int nx, ny, nz, dist; short w; - PlaySound(DIGI_FIREBALL1, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_FIREBALL1, sp, v3df_none); nx = sp->x; ny = sp->y; @@ -17430,7 +17429,7 @@ InitBoltTrap(short SpriteNum) int nx, ny, nz, dist; short w; - PlaySound(DIGI_RIOTFIRE, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_RIOTFIRE, sp, v3df_none); nx = sp->x; ny = sp->y; @@ -17509,7 +17508,7 @@ InitEnemyCrossbow(short SpriteNum) if (dist != 0) wu->zchange = wp->zvel = (wp->xvel * (SPRITEp_UPPER(u->tgt_sp) - wp->z)) / dist; - PlaySound(DIGI_STAR, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STAR, sp, v3df_none); return w; } @@ -17560,7 +17559,7 @@ InitSpearTrap(short SpriteNum) //if (dist != 0) //wu->zchange = wp->zvel = (wp->xvel * (SPRITEp_UPPER(u->tgt_sp) - wp->z)) / dist; - PlaySound(DIGI_STAR, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_STAR, sp, v3df_none); return w; } @@ -17978,7 +17977,7 @@ InitUzi(PLAYERp pp) } if (FireSnd) - PlaySound(DIGI_UZIFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_UZIFIRE, pp, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; @@ -18087,7 +18086,7 @@ InitUzi(PLAYERp pp) { extern STATE s_TrashCanPain[]; - PlaySound(DIGI_TRASHLID, &hsp->x, &hsp->y, &hsp->z, v3df_none); + PlaySound(DIGI_TRASHLID, hsp, v3df_none); if (hu->WaitTics <= 0) { hu->WaitTics = SEC(2); @@ -18145,10 +18144,10 @@ InitUzi(PLAYERp pp) if (RANDOM_P2(1024) < 100) { - PlaySound(DIGI_RICHOCHET1,&wp->x, &wp->y, &wp->z, v3df_none); + PlaySound(DIGI_RICHOCHET1,wp, v3df_none); } else if (RANDOM_P2(1024) < 100) - PlaySound(DIGI_RICHOCHET2,&wp->x, &wp->y, &wp->z, v3df_none); + PlaySound(DIGI_RICHOCHET2,wp, v3df_none); return 0; } @@ -18172,7 +18171,7 @@ InitEMP(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -1); - PlaySound(DIGI_RAILFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_RAILFIRE, pp, v3df_dontpan|v3df_doppler); InitTracerUzi(pp); @@ -18300,7 +18299,7 @@ InitEMP(PLAYERp pp) SetAttach(hitinfo.sprite, j); wu->sz = sprite[hitinfo.sprite].z - wp->z; if (RANDOM_RANGE(1000) > 500) - PlayerSound(DIGI_YOULOOKSTUPID,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp); + PlayerSound(DIGI_YOULOOKSTUPID, v3df_follow|v3df_dontpan,pp); } else { @@ -18338,7 +18337,7 @@ InitTankShell(short SpriteNum, PLAYERp pp) short w; if (!SW_SHAREWARE) - PlaySound(DIGI_CANNON, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_CANNON, pp, v3df_dontpan|v3df_doppler); w = SpawnSprite(STAT_MISSILE, 0, s_TankShell, sp->sectnum, sp->x, sp->y, sp->z, sp->ang, TANK_SHELL_VELOCITY); @@ -18723,7 +18722,7 @@ InitSobjMachineGun(short SpriteNum, PLAYERp pp) //sound = (++sound)&1; //if (sound == 0) - PlaySound(DIGI_BOATFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BOATFIRE, pp, v3df_dontpan|v3df_doppler); nx = sp->x; ny = sp->y; @@ -18970,7 +18969,7 @@ SpawnBoatSparks(PLAYERp pp, short hit_sect, short hit_wall, int hit_x, int hit_y HitscanSpriteAdjust(j, hit_wall); if (RANDOM_P2(1024) < 100) - PlaySound(DIGI_RICHOCHET1,&wp->x, &wp->y, &wp->z, v3df_none); + PlaySound(DIGI_RICHOCHET1,wp, v3df_none); return j; } @@ -19055,7 +19054,7 @@ SpawnTurretSparks(SPRITEp sp, short hit_sect, short hit_wall, int hit_x, int hit HitscanSpriteAdjust(j, hit_wall); if (RANDOM_P2(1024) < 100) - PlaySound(DIGI_RICHOCHET1, &wp->x, &wp->y, &wp->z, v3df_none); + PlaySound(DIGI_RICHOCHET1, wp, v3df_none); return j; } @@ -19117,7 +19116,7 @@ InitTurretMgun(SECTOR_OBJECTp sop) SPRITEp sp,ep; int xvect,yvect,zvect; - PlaySound(DIGI_BOATFIRE, &sop->xmid, &sop->ymid, &sop->zmid, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_BOATFIRE, (vec3_t*)sop, v3df_dontpan|v3df_doppler); for (i = 0; sop->sp_num[i] != -1; i++) { @@ -19342,9 +19341,9 @@ InitEnemyUzi(short SpriteNum) { if (sp->pal == PALETTE_PLAYER3 || sp->pal == PALETTE_PLAYER5 || sp->pal == PAL_XLAT_LT_GREY || sp->pal == PAL_XLAT_LT_TAN) - PlaySound(DIGI_M60, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_M60, sp, v3df_none); else - PlaySound(DIGI_NINJAUZIATTACK, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_NINJAUZIATTACK, sp, v3df_none); } if (hitinfo.wall >= 0) @@ -19420,10 +19419,10 @@ InitEnemyUzi(short SpriteNum) if (RANDOM_P2(1024) < 100) { - PlaySound(DIGI_RICHOCHET1,&wp->x, &wp->y, &wp->z, v3df_none); + PlaySound(DIGI_RICHOCHET1,wp, v3df_none); } else if (RANDOM_P2(1024) < 100) - PlaySound(DIGI_RICHOCHET2,&wp->x, &wp->y, &wp->z, v3df_none); + PlaySound(DIGI_RICHOCHET2,wp, v3df_none); return 0; } @@ -19446,7 +19445,7 @@ InitGrenade(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -1); - PlaySound(DIGI_30MMFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_30MMFIRE, pp, v3df_dontpan|v3df_doppler); // Make sprite shade brighter u->Vis = 128; @@ -19552,7 +19551,7 @@ InitSpriteGrenade(short SpriteNum) int dist; - PlaySound(DIGI_30MMFIRE, &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_30MMFIRE, sp, v3df_dontpan|v3df_doppler); nx = sp->x; ny = sp->y; @@ -19620,7 +19619,7 @@ InitMine(PLAYERp pp) PlayerUpdateAmmo(pp, u->WeaponNum, -1); - PlaySound(DIGI_MINETHROW, &pp->posx, &pp->posy, &pp->posz, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_MINETHROW, pp, v3df_dontpan|v3df_doppler); if (pp->cursectnum < 0) return 0; @@ -19692,7 +19691,7 @@ InitEnemyMine(short SpriteNum) int tvel; - PlaySound(DIGI_MINETHROW, &sp->x, &sp->y, &sp->z, v3df_dontpan|v3df_doppler); + PlaySound(DIGI_MINETHROW, sp, v3df_dontpan|v3df_doppler); nx = sp->x; ny = sp->y; @@ -19800,7 +19799,7 @@ InitFireball(PLAYERp pp) PlayerUpdateAmmo(pp, WPN_HOTHEAD, -1); - PlaySound(DIGI_HEADFIRE, &pp->posx, &pp->posy, &pp->posz, v3df_none); + PlaySound(DIGI_HEADFIRE, pp, v3df_none); // Make sprite shade brighter u->Vis = 128; @@ -19891,7 +19890,7 @@ InitEnemyFireball(short SpriteNum) tsp = u->tgt_sp; - PlaySound(DIGI_FIREBALL1, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_FIREBALL1, sp, v3df_none); // get angle to player and also face player when attacking sp->ang = NORM_ANGLE(getangle(tsp->x - sp->x, tsp->y - sp->y)); @@ -20290,7 +20289,7 @@ SpawnSplash(short SpriteNum) if (sectu && TEST(sectp->floorstat, FLOOR_STAT_PLAX)) return 0; - PlaySound(DIGI_SPLASH1, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SPLASH1, sp, v3df_none); DoActorZrange(SpriteNum); MissileWaterAdjust(SpriteNum); @@ -20423,7 +20422,7 @@ MissileHitDiveArea(short SpriteNum) SpriteWarpToUnderwater(sp); //SpawnUnderSplash(sp - sprite); u->ret = 0; - PlaySound(DIGI_PROJECTILEWATERHIT, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_PROJECTILEWATERHIT, sp, v3df_none); return TRUE; } else if (SpriteInUnderwaterArea(sp)) @@ -20463,7 +20462,7 @@ SpawnBubble(short SpriteNum) bp = &sprite[b]; bu = User[b]; - //PlaySound(DIGI_BUBBLES, &sp->x, &sp->y, &sp->z, v3df_none); + //PlaySound(DIGI_BUBBLES, sp, v3df_none); bp->xrepeat = 8 + (RANDOM_P2(8 << 8) >> 8); bp->yrepeat = bp->xrepeat; @@ -21427,7 +21426,7 @@ DoShrapVelocity(int16_t SpriteNum) short wall_ang, dang; short hit_sprite = -2; SPRITEp hsp; -// PlaySound(DIGI_DHCLUNK, &sp->x, &sp->y, &sp->z, v3df_dontpan); +// PlaySound(DIGI_DHCLUNK, sp, v3df_dontpan); hit_sprite = NORM_SPRITE(u->ret); hsp = &sprite[hit_sprite]; @@ -21449,7 +21448,7 @@ DoShrapVelocity(int16_t SpriteNum) wph = &wall[hit_wall]; -// PlaySound(DIGI_DHCLUNK, &sp->x, &sp->y, &sp->z, v3df_dontpan); +// PlaySound(DIGI_DHCLUNK, sp, v3df_dontpan); nw = wall[hit_wall].point2; wall_ang = NORM_ANGLE(getangle(wall[nw].x - wph->x, wall[nw].y - wph->y)+512); @@ -21523,10 +21522,10 @@ DoShrapVelocity(int16_t SpriteNum) switch (u->ID) { case UZI_SHELL: - PlaySound(DIGI_SHELL, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SHELL, sp, v3df_none); break; case SHOT_SHELL: - PlaySound(DIGI_SHOTSHELLSPENT, &sp->x, &sp->y, &sp->z, v3df_none); + PlaySound(DIGI_SHOTSHELLSPENT, sp, v3df_none); break; } } @@ -21623,9 +21622,9 @@ ShrapKillSprite(short SpriteNum) sp->clipdist = SPRITEp_SIZE_X(sp); SpawnFloorSplash(SpriteNum); if (RANDOM_RANGE(1000) < 500) - PlaySound(DIGI_GIBS1,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_GIBS1, sp, v3df_none); else - PlaySound(DIGI_GIBS2,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_GIBS2, sp, v3df_none); if (rnd_num > 683) { QueueGeneric(SpriteNum,900); @@ -21645,9 +21644,9 @@ ShrapKillSprite(short SpriteNum) sp->clipdist = SPRITEp_SIZE_X(sp); SpawnFloorSplash(SpriteNum); if (RANDOM_RANGE(1000) < 500) - PlaySound(DIGI_GIBS1,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_GIBS1, sp, v3df_none); else - PlaySound(DIGI_GIBS2,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_GIBS2, sp, v3df_none); if (rnd_num > 683) { QueueGeneric(SpriteNum,915); diff --git a/source/sw/src/zilla.cpp b/source/sw/src/zilla.cpp index 6193c911b..17879bd98 100644 --- a/source/sw/src/zilla.cpp +++ b/source/sw/src/zilla.cpp @@ -35,7 +35,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "quake.h" #include "actor.h" #include "track.h" -#include "fx_man.h" #include "gamecontrol.h" #include "mapinfo.h" @@ -719,23 +718,22 @@ int DoZillaMove(short SpriteNum) SPRITEp sp = &sprite[SpriteNum]; USERp u = User[SpriteNum]; short choose; - static int handle; //if (TEST(u->Flags,SPR_SLIDING)) //DoActorSlide(SpriteNum); // Random Zilla taunts - if (!FX_SoundValidAndActive(handle)) + if (!SoundValidAndActive(sp, CHAN_AnimeMad)) { choose = STD_RANDOM_RANGE(1000); if (choose > 990) - handle = PlaySound(DIGI_Z16004,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_Z16004, sp, v3df_none, CHAN_AnimeMad); else if (choose > 985) - handle = PlaySound(DIGI_Z16004,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_Z16004, sp, v3df_none, CHAN_AnimeMad); else if (choose > 980) - handle = PlaySound(DIGI_Z16004,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_Z16004, sp, v3df_none, CHAN_AnimeMad); else if (choose > 975) - handle = PlaySound(DIGI_Z16004,&sp->x,&sp->y,&sp->z,v3df_none); + PlaySound(DIGI_Z16004, sp, v3df_none, CHAN_AnimeMad); } @@ -758,7 +756,7 @@ int DoZillaStomp(short SpriteNum) { SPRITEp sp = &sprite[SpriteNum]; - PlaySound(DIGI_ZILLASTOMP,&sp->x,&sp->y,&sp->z,v3df_follow); + PlaySound(DIGI_ZILLASTOMP, sp, v3df_follow); return 0; } diff --git a/source/thirdparty/include/fix16.h b/source/thirdparty/include/fix16.h index 54a31acc1..f02a4d41f 100644 --- a/source/thirdparty/include/fix16.h +++ b/source/thirdparty/include/fix16.h @@ -37,7 +37,7 @@ static FORCE_INLINE CONSTEXPR fix16_t fix16_from_int(int a) { return a * fix static FORCE_INLINE CONSTEXPR float fix16_to_float(fix16_t a) { return (float)a / fix16_one; } static FORCE_INLINE CONSTEXPR double fix16_to_dbl(fix16_t a) { return (double)a / fix16_one; } -static inline int fix16_to_int(fix16_t a) +static inline constexpr int fix16_to_int(fix16_t a) { #ifdef FIXMATH_NO_ROUNDING return (a >> 16); diff --git a/wadsrc/static/demolition/dsempty.lmp b/wadsrc/static/demolition/dsempty.lmp new file mode 100644 index 000000000..cb6f1d2fc Binary files /dev/null and b/wadsrc/static/demolition/dsempty.lmp differ diff --git a/wadsrc/static/demolition/menudef.txt b/wadsrc/static/demolition/menudef.txt index aeee33bf0..517c71077 100644 --- a/wadsrc/static/demolition/menudef.txt +++ b/wadsrc/static/demolition/menudef.txt @@ -969,29 +969,12 @@ OptionMenu "MouseOptions" //protected // //------------------------------------------------------------------------------------------- -OptionMenu "JoystickOptions"//Defaults" //protected +OptionMenu "JoystickOptions" //protected { Title "$JOYMNU_OPTIONS" - Option "$JOYMNU_ENABLE", "use_joystick", "YesNo" - Option "$JOYMNU_NOMENU", "m_blockcontrollers", "YesNo" - /*IfOption(Windows) - { - Option "$JOYMNU_DINPUT", "joy_dinput", "YesNo" - Option "$JOYMNU_XINPUT", "joy_xinput", "YesNo" - Option "$JOYMNU_PS2", "joy_ps2raw", "YesNo" - }*/ - StaticText "" - StaticTextSwitchable "$JOYMNU_NOCON", "$JOYMNU_CONFIG", "ConfigureMessage" - StaticTextSwitchable " ", "$JOYMNU_DISABLED1", "ConnectMessage1" - StaticTextSwitchable " ", "$JOYMNU_DISABLED2", "ConnectMessage2" - - // The rest will be filled in by joystick code if devices get connected or disconnected + // This will be filled in by joystick code if devices get connected or disconnected } -OptionMenu "JoystickOptions1" //protected -{ - Title "$JOYMNU_OPTIONS" -} OptionValue "JoyAxisMapNames" { @@ -1324,8 +1307,7 @@ OptionMenu SoundOptions //protected Slider "$MODMNU_MASTERVOLUME", "snd_mastervolume", 0, 1, 0.05, 2 StaticText " " Option "$SNDMNU_SNDENABLED", "snd_enabled", "YesNo" - Slider "$SNDMNU_SFXVOLUME", "snd_fxvolume", 0, 255, 2, 1 - //Slider "$SNDMNU_SFXVOLUME", "snd_sfxvolume", 0, 1, 0.05, 2 // Todo: Change value type + Slider "$SNDMNU_SFXVOLUME", "snd_sfxvolume", 0, 1, 0.05, 2 Option "$SNDMNU_MUSENABLED", "mus_enabled", "YesNo" Slider "$SNDMNU_MUSICVOLUME", "mus_volume", 0, 1, 0.05, 2 Option "$SNDMNU_MENUSOUND", "menu_sounds", "OnOff" // placeholder until the slider can be made to work @@ -1334,7 +1316,6 @@ OptionMenu SoundOptions //protected Option "$SNDMNU_MIDIDEVICE", "snd_mididevice", "MidiDevices" StaticText " " //Option "$SNDMNU_UNDERWATERREVERB", "snd_waterreverb", "OnOff" - //Option "$SNDMNU_RANDOMIZEPITCHES", "snd_pitched", "OnOff" Slider "$SNDMNU_CHANNELS", "snd_numchannels", 64, 128, 8, 0 staticText "" ifgame (Blood, ShadowWarrior, Redneck, RedneckRides) @@ -1370,7 +1351,6 @@ OptionMenu AdvSoundOptions //protected Title "$ADVSNDMNU_TITLE" Option "$ADVSNDMNU_SAMPLERATE", "snd_mixrate", "SampleRates" //Option "$ADVSNDMNU_HRTF", "snd_hrtf", "AutoOffOn" - Option "$ADVSNDMNU_FLIPSTEREO", "snd_reversestereo", "OnOff" StaticText " " //Option "$SNDMNU_BACKGROUND", "i_soundinbackground", "OnOff" //StaticText " " @@ -1385,7 +1365,7 @@ OptionMenu AdvSoundOptions //protected Submenu "$SNDMNU_MIDIPLAYER", "MidiPlayerOptions" Submenu "$SNDMNU_MODREPLAYER", "ModReplayerOptions" StaticText " " - Command "$SNDMNU_RESTART", "restartsound" + Command "$SNDMNU_RESTART", "snd_reset" } diff --git a/wadsrc/static/demolition/shaders/glsl/polymost.vp b/wadsrc/static/demolition/shaders/glsl/polymost.vp index 18d65d413..6ba731b59 100644 --- a/wadsrc/static/demolition/shaders/glsl/polymost.vp +++ b/wadsrc/static/demolition/shaders/glsl/polymost.vp @@ -35,5 +35,5 @@ void main() v_fogCoord = abs(eyeCoordPosition.z); v_color = i_color; - v_distance = i_vertPos.z; + v_distance = eyeCoordPosition.z; }