mirror of
https://github.com/DrBeef/Raze.git
synced 2025-01-18 15:11:51 +00:00
Merge commit '40a533402e443a0de1673543642c892ab9c731fd' into powerslave
# Conflicts: # source/audiolib/include/fx_man.h # source/audiolib/include/multivoc.h # source/audiolib/src/_multivc.h # source/audiolib/src/fx_man.cpp # source/audiolib/src/multivoc.cpp
This commit is contained in:
commit
e180d9afd3
246 changed files with 8309 additions and 27165 deletions
|
@ -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} )
|
||||
|
|
|
@ -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
|
||||
* <A HREF="../format.html">here</A>.
|
||||
*
|
||||
* \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 <A HREF="../license.html">Xiph's BSD license</A>.
|
||||
* 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
|
||||
* <A HREF="../license.html">Xiph's BSD license</A>.
|
||||
*
|
||||
* \section getting_started Getting Started
|
||||
*
|
||||
* A good starting point for learning the API is to browse through
|
||||
* the <A HREF="modules.html">modules</A>. 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
|
||||
* <A HREF="../documentation_example_code.html">example code</A>.
|
||||
*
|
||||
* \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'
|
||||
* <A HREF="http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning">libtool version numbers</A>,
|
||||
* 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
|
|
@ -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 <assert.h>
|
||||
#define FLAC__ASSERT(x) assert(x)
|
||||
#define FLAC__ASSERT_DECLARATION(x) x
|
||||
#else
|
||||
#define FLAC__ASSERT(x)
|
||||
#define FLAC__ASSERT_DECLARATION(x)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -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 <stdlib.h> /* 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
|
|
@ -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
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -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 <stdint.h>.
|
||||
*/
|
||||
|
||||
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 <stdint.h>. */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -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 <inttypes.h>
|
||||
#endif
|
||||
#if INCLUDE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
#if INCLUDE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#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
|
|
@ -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 <stddef.h>
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
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 */
|
|
@ -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 <stdint.h>
|
||||
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 <sys/types.h>
|
||||
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 <sys/types.h>
|
||||
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 <inttypes.h>
|
||||
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 <sys/types.h>
|
||||
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 <inttypes.h>
|
||||
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 <ogg/config_types.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _OS_TYPES_H */
|
|
@ -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 <ogg/ogg.h>
|
||||
|
||||
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
|
||||
|
|
@ -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 <stdio.h>
|
||||
#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
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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/.+")
|
||||
|
|
|
@ -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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.
|
||||
|
||||
<signature of Ty Coon>, 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.
|
|
@ -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 <inttypes.h>
|
||||
|
||||
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
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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
|
|
@ -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 <inttypes.h>
|
||||
#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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 <inttypes.h>
|
||||
|
||||
#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
|
|
@ -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__
|
|
@ -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
|
|
@ -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 <inttypes.h>
|
||||
|
||||
#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
|
|
@ -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
|
|
@ -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 <typename T>
|
||||
static inline conditional_t< is_signed<T>::value, make_unsigned_t<T>, make_signed_t<T> > FLIP_SIGN(T src)
|
||||
{
|
||||
static constexpr make_unsigned_t<T> msb = ((make_unsigned_t<T>)1) << (sizeof(T) * CHAR_BIT - 1u);
|
||||
return src ^ msb;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline enable_if_t<is_signed<T>::value, T> SCALE_SAMPLE(T src, float volume)
|
||||
{
|
||||
return (T)Blrintf((float)src * volume);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline T CONVERT_SAMPLE_FROM_SIGNED(int src);
|
||||
|
||||
template<>
|
||||
inline int16_t CONVERT_SAMPLE_FROM_SIGNED<int16_t>(int src)
|
||||
{
|
||||
return src;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline int CONVERT_SAMPLE_TO_SIGNED(T src);
|
||||
|
||||
template<>
|
||||
inline int CONVERT_SAMPLE_TO_SIGNED<int16_t>(int16_t src)
|
||||
{
|
||||
return src;
|
||||
}
|
||||
|
||||
template <typename S, typename D>
|
||||
static inline int CONVERT_LE_SAMPLE_TO_SIGNED(S src);
|
||||
|
||||
template<>
|
||||
inline int CONVERT_LE_SAMPLE_TO_SIGNED<uint8_t, int16_t>(uint8_t src)
|
||||
{
|
||||
return FLIP_SIGN(src) << 8;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline int CONVERT_LE_SAMPLE_TO_SIGNED<int16_t, int16_t>(int16_t src)
|
||||
{
|
||||
return B_LITTLE16(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static int CLAMP_SAMPLE(int src);
|
||||
|
||||
template<>
|
||||
inline int CLAMP_SAMPLE<int16_t>(int src)
|
||||
{
|
||||
return clamp(src, INT16_MIN, INT16_MAX);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T MIX_SAMPLES(int signed_sample, T untouched_sample)
|
||||
{
|
||||
return CONVERT_SAMPLE_FROM_SIGNED<T>(CLAMP_SAMPLE<T>(signed_sample + CONVERT_SAMPLE_TO_SIGNED<T>(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 <typename S, typename D> uint32_t MV_MixMono(struct VoiceNode * const voice, uint32_t length);
|
||||
template <typename S, typename D> uint32_t MV_MixStereo(struct VoiceNode * const voice, uint32_t length);
|
||||
template <typename T> void MV_Reverb(char const *src, char * const dest, const float volume, int count);
|
||||
|
||||
// implemented in mixst.c
|
||||
template <typename S, typename D> uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length);
|
||||
template <typename S, typename D> 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
|
|
@ -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<int>(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++);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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);
|
||||
|
|
@ -1,422 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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 <inttypes.h>
|
||||
|
||||
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);
|
|
@ -1,319 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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__
|
|
@ -1,838 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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 <mmsystem.h>
|
||||
|
||||
#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:
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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);
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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:
|
|
@ -1,537 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
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<uint32_t>(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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 <inttypes.h>
|
||||
#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 }
|
||||
};
|
|
@ -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
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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<uint8_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
||||
template uint32_t MV_MixStereo<uint8_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
||||
template uint32_t MV_MixMono<int16_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
||||
template uint32_t MV_MixStereo<int16_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
||||
template void MV_Reverb<int16_t>(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 <typename S, typename D>
|
||||
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<S, D>(source[position >> 16]);
|
||||
|
||||
position += rate;
|
||||
|
||||
*dest = MIX_SAMPLES<D>(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 <typename S, typename D>
|
||||
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<S, D>(source[position >> 16]);
|
||||
|
||||
position += rate;
|
||||
|
||||
*dest = MIX_SAMPLES<D>(SCALE_SAMPLE(isample0, volume*voice->LeftVolume), *dest);
|
||||
*(dest + (MV_RightChannelOffset / sizeof(*dest)))
|
||||
= MIX_SAMPLES<D>(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 <typename T>
|
||||
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<T>(*input++);
|
||||
*output++ = CONVERT_SAMPLE_FROM_SIGNED<T>(SCALE_SAMPLE(isample0, volume));
|
||||
}
|
||||
while (--count > 0);
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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<uint8_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
||||
template uint32_t MV_MixStereoStereo<uint8_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
||||
template uint32_t MV_MixMonoStereo<int16_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
||||
template uint32_t MV_MixStereoStereo<int16_t, int16_t>(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 <typename S, typename D>
|
||||
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<S, D>(source[(position >> 16) << 1]);
|
||||
auto const isample1 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[((position >> 16) << 1) + 1]);
|
||||
|
||||
position += rate;
|
||||
|
||||
*dest = MIX_SAMPLES<D>((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 <typename S, typename D>
|
||||
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<S, D>(source[(position >> 16) << 1]);
|
||||
auto const isample1 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[((position >> 16) << 1) + 1]);
|
||||
|
||||
position += rate;
|
||||
|
||||
*dest = MIX_SAMPLES<D>(SCALE_SAMPLE(isample0, volume*voice->LeftVolume), *dest);
|
||||
*(dest + (MV_RightChannelOffset / sizeof(*dest)))
|
||||
= MIX_SAMPLES<D>(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;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
{
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
|
@ -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 <inttypes.h>
|
||||
|
||||
uint32_t PITCH_GetScale(int pitchoffset);
|
||||
#endif
|
|
@ -1,472 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
||||
|
||||
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 <vorbis/vorbisfile.h>
|
||||
#elif defined GEKKO
|
||||
# define USING_TREMOR
|
||||
# include <tremor/ivorbisfile.h>
|
||||
#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
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <shellapi.h>
|
||||
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -27,8 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include <string.h>
|
||||
#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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 <all|health|weapons|ammo|armor|keys|inventory>: 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 <xdim> <ydim> <bpp> <fullscreen>: change the video mode",osdcmd_vidmode);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "compat.h"
|
||||
#include "cache1d.h"
|
||||
|
||||
#include "common_game.h"
|
||||
|
||||
#include "misc.h"
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<uint8_t> 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<uint8_t> 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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 "<lumpname>.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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<char *> 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];
|
||||
|
|
|
@ -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_
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "compat.h"
|
||||
#include "baselayer.h"
|
||||
#include "build.h"
|
||||
#include "cache1d.h"
|
||||
|
||||
#include "matrix.h"
|
||||
#include "../../glbackend/glbackend.h"
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <stdint.h>
|
||||
#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<TArray<uint8_t>> pseudocache;
|
||||
|
||||
void cacheAllocateBlock(intptr_t *newhandle, int32_t newbytes, uint8_t *)
|
||||
{
|
||||
pseudocache.Reserve(1);
|
||||
auto& buffer = pseudocache.Last();
|
||||
buffer.Resize(newbytes);
|
||||
*newhandle = reinterpret_cast<intptr_t>(buffer.Data());
|
||||
}
|
||||
|
|
@ -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; i<argc; i++)
|
||||
{
|
||||
if (str && !Bstrcasecmp(argv[i], str))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////
|
||||
|
||||
// Copy FN to WBUF and append an extension if it's not there, which is checked
|
||||
// case-insensitively.
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "engine_priv.h"
|
||||
#include "baselayer.h"
|
||||
#include "scriptfile.h"
|
||||
#include "cache1d.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "mdsprite.h" // md3model_t
|
||||
#include "colmatch.h"
|
||||
|
@ -121,7 +121,8 @@ enum scripttoken_t
|
|||
T_DST_COLOR, T_ONE_MINUS_DST_COLOR,
|
||||
T_SHADERED, T_SHADEGREEN, T_SHADEBLUE,
|
||||
T_SHADEFACTOR,
|
||||
T_IFCRC,
|
||||
T_IFCRC,T_IFMATCH,T_CRC32,
|
||||
T_SIZE,
|
||||
T_NEWGAMECHOICES,
|
||||
T_RFFDEFINEID,
|
||||
T_EXTRA,
|
||||
|
@ -129,7 +130,6 @@ enum scripttoken_t
|
|||
};
|
||||
|
||||
static int32_t lastmodelid = -1, lastvoxid = -1, modelskin = -1, lastmodelskin = -1, seenframe = 0;
|
||||
static int32_t nextvoxid = 0;
|
||||
static char *faketilebuffer = NULL;
|
||||
static int32_t faketilebuffersiz = 0;
|
||||
|
||||
|
@ -649,8 +649,10 @@ static int32_t defsparser(scriptfile *script)
|
|||
int32_t havexoffset = 0, haveyoffset = 0, haveextra = 0;
|
||||
int32_t xoffset = 0, yoffset = 0;
|
||||
int32_t istexture = 0;
|
||||
int32_t tilecrc = 0;
|
||||
uint8_t have_ifcrc = 0;
|
||||
int32_t tile_crc32 = 0;
|
||||
vec2_t tile_size{};
|
||||
uint8_t have_crc32 = 0;
|
||||
uint8_t have_size = 0;
|
||||
int32_t extra = 0;
|
||||
|
||||
static const tokenlist tilefromtexturetokens[] =
|
||||
|
@ -666,6 +668,7 @@ static int32_t defsparser(scriptfile *script)
|
|||
{ "nofullbright", T_NOFULLBRIGHT },
|
||||
{ "texture", T_TEXTURE },
|
||||
{ "ifcrc", T_IFCRC },
|
||||
{ "ifmatch", T_IFMATCH },
|
||||
{ "extra", T_EXTRA },
|
||||
};
|
||||
|
||||
|
@ -694,9 +697,40 @@ static int32_t defsparser(scriptfile *script)
|
|||
yoffset = clamp(yoffset, -128, 127);
|
||||
break;
|
||||
case T_IFCRC:
|
||||
scriptfile_getsymbol(script, &tilecrc);
|
||||
have_ifcrc = 1;
|
||||
scriptfile_getsymbol(script, &tile_crc32);
|
||||
have_crc32 = 1;
|
||||
break;
|
||||
case T_IFMATCH:
|
||||
{
|
||||
char *ifmatchend;
|
||||
|
||||
static const tokenlist ifmatchtokens[] =
|
||||
{
|
||||
{ "crc32", T_CRC32 },
|
||||
{ "size", T_SIZE },
|
||||
};
|
||||
|
||||
if (scriptfile_getbraces(script,&ifmatchend)) break;
|
||||
while (script->textptr < 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;
|
||||
|
|
|
@ -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<xdimen; x++)
|
||||
{
|
||||
if (daumost[x]>=0 && daumost[x]<ydimen)
|
||||
*(char *)(frameplace + x + bytesperline*daumost[x]) = editorcolors[13];
|
||||
if (dadmost[x]>=0 && dadmost[x]<ydimen)
|
||||
*(char *)(frameplace + x + bytesperline*dadmost[x]) = editorcolors[14];
|
||||
}
|
||||
#endif
|
||||
|
||||
videoEndDrawing(); //}}}
|
||||
}
|
||||
|
||||
|
@ -6786,16 +6796,13 @@ void dorotspr_handle_bit2(int32_t *sxptr, int32_t *syptr, int32_t *z, int32_t da
|
|||
int32_t zoomsc, sx=*sxptr, sy=*syptr;
|
||||
int32_t ouryxaspect = yxaspect, ourxyaspect = xyaspect;
|
||||
|
||||
if ((dastat & RS_ALIGN_MASK) && (dastat & RS_ALIGN_MASK) != RS_ALIGN_MASK)
|
||||
sx += NEGATE_ON_CONDITION(scale(120<<16,xdim,ydim) - (160<<16), !(dastat & RS_ALIGN_R));
|
||||
|
||||
sy += rotatesprite_y_offset;
|
||||
|
||||
// screen center to s[xy], 320<<16 coords.
|
||||
const int32_t normxofs = sx-(320<<15), normyofs = sy-(200<<15);
|
||||
|
||||
if (!(dastat & RS_STRETCH) && 4*ydim <= 3*xdim)
|
||||
{
|
||||
if ((dastat & RS_ALIGN_MASK) && (dastat & RS_ALIGN_MASK) != RS_ALIGN_MASK)
|
||||
sx += NEGATE_ON_CONDITION(scale(120<<16,xdim,ydim) - (160<<16), !(dastat & RS_ALIGN_R));
|
||||
|
||||
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
|
||||
ydim = scale(xdim, 3, 4);
|
||||
else
|
||||
|
@ -6808,6 +6815,9 @@ void dorotspr_handle_bit2(int32_t *sxptr, int32_t *syptr, int32_t *z, int32_t da
|
|||
ouryxaspect = mulscale16(ouryxaspect, rotatesprite_yxaspect);
|
||||
ourxyaspect = divscale16(ourxyaspect, rotatesprite_yxaspect);
|
||||
|
||||
// screen center to s[xy], 320<<16 coords.
|
||||
const int32_t normxofs = sx-(320<<15), normyofs = sy-(200<<15);
|
||||
|
||||
// nasty hacks go here
|
||||
if (!(dastat & RS_NOCLIP))
|
||||
{
|
||||
|
@ -7316,6 +7326,7 @@ static void dosetaspect(void)
|
|||
{
|
||||
oxyaspect = xyaspect;
|
||||
j = xyaspect*320;
|
||||
horizycent = (ydim*4)>>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],
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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 <execinfo.h>
|
||||
#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.
|
||||
|
||||
//
|
||||
|
|
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue