mirror of
https://github.com/ZDoom/ZMusic.git
synced 2024-12-11 21:11:00 +00:00
faa997b986
Changelog: * Added an ability to disable the automatical arpeggio * Updated the GENS chip emulator from the 2.10 into GS/II (thanks to @freq-mod for the help) * Added an ability to set number of loops * Added an ability to disable/enable playing of selected MIDI channels * Fixed memory damages and crashes while playing XMI files * Added the chip channels allocation mode option * Fixed the playback of multi-song XMI files * Added an ability to switch the XMI song on the fly And also: * Fixed the work on big endian processors * Fixed ARM64 build on some platforms * Improved support of the EA-MUS files (Thanks to [dashodanger](https://github.com/dashodanger)) * Fixed crash on attempt to change the volume of a blank note
275 lines
9 KiB
C
275 lines
9 KiB
C
/*
|
|
* Wohlstand's OPN2 Bank File - a bank format to store OPN2 timbre data and setup
|
|
*
|
|
* Copyright (c) 2018-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#ifndef WOPN_FILE_H
|
|
#define WOPN_FILE_H
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Solaris defines the integer types regardless of what C/C++ standard is actually available,
|
|
* so avoid defining them at all by ourselves. */
|
|
#if !defined(WOPN_STDINT_TYPEDEFS_NOT_NEEDED) && defined(__sun)
|
|
# define WOPN_STDINT_TYPEDEFS_NOT_NEEDED
|
|
#endif
|
|
|
|
#if !defined(WOPN_STDINT_TYPEDEFS_NEEDED) && !defined(WOPN_STDINT_TYPEDEFS_NOT_NEEDED)
|
|
# if !defined(__STDC_VERSION__) || \
|
|
(defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901L)) || \
|
|
defined(__STRICT_ANSI__) || \
|
|
!defined(__cplusplus)
|
|
# define WOPN_STDINT_TYPEDEFS_NEEDED
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef WOPN_STDINT_TYPEDEFS_NEEDED
|
|
typedef signed char int8_t;
|
|
typedef unsigned char uint8_t;
|
|
typedef signed short int int16_t;
|
|
typedef unsigned short int uint16_t;
|
|
#endif
|
|
|
|
/* Type of chip for which a bank has been designed */
|
|
typedef enum WOPN_ChipType
|
|
{
|
|
/* The Yamaha OPN2 chip, alias YM2612 YM3438 */
|
|
WOPN_Chip_OPN2 = 0,
|
|
/* The Yamaha OPNA chip, alias YM2608 */
|
|
WOPN_Chip_OPNA = 1
|
|
} WOPN_ChipType;
|
|
|
|
/* Volume scaling model implemented in the libOPNMIDI */
|
|
typedef enum WOPN_VolumeModel
|
|
{
|
|
WOPN_VM_Generic = 0
|
|
} WOPN_VolumeModel;
|
|
|
|
typedef enum WOPN_InstrumentFlags
|
|
{
|
|
/* Is pseudo eight-operator (two 4-operator voices) instrument */
|
|
WOPN_Ins_Pseudo8op = 0x01,
|
|
/* Is a blank instrument entry */
|
|
WOPN_Ins_IsBlank = 0x02,
|
|
|
|
/* Mask of the flags range */
|
|
WOPN_Ins_ALL_MASK = 0x03
|
|
} WOPN_InstrumentFlags;
|
|
|
|
/* Error codes */
|
|
typedef enum WOPN_ErrorCodes
|
|
{
|
|
WOPN_ERR_OK = 0,
|
|
/* Magic number is not maching */
|
|
WOPN_ERR_BAD_MAGIC,
|
|
/* Too short file */
|
|
WOPN_ERR_UNEXPECTED_ENDING,
|
|
/* Zero banks count */
|
|
WOPN_ERR_INVALID_BANKS_COUNT,
|
|
/* Version of file is newer than supported by current version of library */
|
|
WOPN_ERR_NEWER_VERSION,
|
|
/* Out of memory */
|
|
WOPN_ERR_OUT_OF_MEMORY,
|
|
/* Given null pointer memory data */
|
|
WOPN_ERR_NULL_POINTER
|
|
} WOPN_ErrorCodes;
|
|
|
|
/* OPN2 Oerators data */
|
|
typedef struct WOPNOperator
|
|
{
|
|
/* Detune and frequency multiplication register data */
|
|
uint8_t dtfm_30;
|
|
/* Total level register data */
|
|
uint8_t level_40;
|
|
/* Rate scale and attack register data */
|
|
uint8_t rsatk_50;
|
|
/* Amplitude modulation enable and Decay-1 register data */
|
|
uint8_t amdecay1_60;
|
|
/* Decay-2 register data */
|
|
uint8_t decay2_70;
|
|
/* Sustain and Release register data */
|
|
uint8_t susrel_80;
|
|
/* SSG-EG register data */
|
|
uint8_t ssgeg_90;
|
|
} WOPNOperator;
|
|
|
|
/* Instrument entry */
|
|
typedef struct WOPNInstrument
|
|
{
|
|
/* Title of the instrument */
|
|
char inst_name[34];
|
|
/* MIDI note key (half-tone) offset for an instrument (or a first voice in pseudo-4-op mode) */
|
|
int16_t note_offset;
|
|
/* Reserved */
|
|
int8_t midi_velocity_offset;
|
|
/* Percussion MIDI base tone number at which this drum will be played */
|
|
uint8_t percussion_key_number;
|
|
/* Enum WOPN_InstrumentFlags */
|
|
uint8_t inst_flags;
|
|
/* Feedback and Algorithm register data */
|
|
uint8_t fbalg;
|
|
/* LFO Sensitivity register data */
|
|
uint8_t lfosens;
|
|
/* Operators register data */
|
|
WOPNOperator operators[4];
|
|
/* Millisecond delay of sounding while key is on */
|
|
uint16_t delay_on_ms;
|
|
/* Millisecond delay of sounding after key off */
|
|
uint16_t delay_off_ms;
|
|
} WOPNInstrument;
|
|
|
|
/* Bank entry */
|
|
typedef struct WOPNBank
|
|
{
|
|
/* Name of bank */
|
|
char bank_name[33];
|
|
/* MIDI Bank LSB code */
|
|
uint8_t bank_midi_lsb;
|
|
/* MIDI Bank MSB code */
|
|
uint8_t bank_midi_msb;
|
|
/* Instruments data of this bank */
|
|
WOPNInstrument ins[128];
|
|
} WOPNBank;
|
|
|
|
/* Instrument data file */
|
|
typedef struct OPNIFile
|
|
{
|
|
/* Version of instrument file */
|
|
uint16_t version;
|
|
/* Is this a percussion instrument */
|
|
uint8_t is_drum;
|
|
/* Instrument data */
|
|
WOPNInstrument inst;
|
|
} OPNIFile;
|
|
|
|
/* Bank data file */
|
|
typedef struct WOPNFile
|
|
{
|
|
/* Version of bank file */
|
|
uint16_t version;
|
|
/* Count of melodic banks in this file */
|
|
uint16_t banks_count_melodic;
|
|
/* Count of percussion banks in this file */
|
|
uint16_t banks_count_percussion;
|
|
/* Chip global LFO enable flag and frequency register data */
|
|
uint8_t lfo_freq;
|
|
/* Chip type this bank is designed for */
|
|
uint8_t chip_type;
|
|
/* Reserved (Enum WOPN_VolumeModel) */
|
|
uint8_t volume_model;
|
|
/* dynamically allocated data Melodic banks array */
|
|
WOPNBank *banks_melodic;
|
|
/* dynamically allocated data Percussive banks array */
|
|
WOPNBank *banks_percussive;
|
|
} WOPNFile;
|
|
|
|
|
|
/**
|
|
* @brief Initialize blank WOPN data structure with allocated bank data
|
|
* @param melodic_banks Count of melodic banks
|
|
* @param percussive_banks Count of percussive banks
|
|
* @return pointer to heap-allocated WOPN data structure or NULL when out of memory or incorrectly given banks counts
|
|
*/
|
|
extern WOPNFile *WOPN_Init(uint16_t melodic_banks, uint16_t percussive_banks);
|
|
|
|
/**
|
|
* @brief Clean up WOPN data file (all allocated bank arrays will be fried too)
|
|
* @param file pointer to heap-allocated WOPN data structure
|
|
*/
|
|
extern void WOPN_Free(WOPNFile *file);
|
|
|
|
/**
|
|
* @brief Compare two bank entries
|
|
* @param bank1 First bank
|
|
* @param bank2 Second bank
|
|
* @return 1 if banks are equal or 0 if there are different
|
|
*/
|
|
extern int WOPN_BanksCmp(const WOPNFile *bank1, const WOPNFile *bank2);
|
|
|
|
|
|
/**
|
|
* @brief Load WOPN bank file from the memory.
|
|
* WOPN data structure will be allocated. (don't forget to clear it with WOPN_Free() after use!)
|
|
* @param mem Pointer to memory block contains raw WOPN bank file data
|
|
* @param length Length of given memory block
|
|
* @param error pointer to integer to return an error code. Pass NULL if you don't want to use error codes.
|
|
* @return Heap-allocated WOPN file data structure or NULL if any error has occouped
|
|
*/
|
|
extern WOPNFile *WOPN_LoadBankFromMem(void *mem, size_t length, int *error);
|
|
|
|
/**
|
|
* @brief Load WOPI instrument file from the memory.
|
|
* You must allocate OPNIFile structure by yourself and give the pointer to it.
|
|
* @param file Pointer to destination OPNIFile structure to fill it with parsed data.
|
|
* @param mem Pointer to memory block contains raw WOPI instrument file data
|
|
* @param length Length of given memory block
|
|
* @return 0 if no errors occouped, or an error code of WOPN_ErrorCodes enumeration
|
|
*/
|
|
extern int WOPN_LoadInstFromMem(OPNIFile *file, void *mem, size_t length);
|
|
|
|
/**
|
|
* @brief Calculate the size of the output memory block
|
|
* @param file Heap-allocated WOPN file data structure
|
|
* @param version Destination version of the file
|
|
* @return Size of the raw WOPN file data
|
|
*/
|
|
extern size_t WOPN_CalculateBankFileSize(WOPNFile *file, uint16_t version);
|
|
|
|
/**
|
|
* @brief Calculate the size of the output memory block
|
|
* @param file Pointer to WOPI file data structure
|
|
* @param version Destination version of the file
|
|
* @return Size of the raw WOPI file data
|
|
*/
|
|
extern size_t WOPN_CalculateInstFileSize(OPNIFile *file, uint16_t version);
|
|
|
|
/**
|
|
* @brief Write raw WOPN into given memory block
|
|
* @param file Heap-allocated WOPN file data structure
|
|
* @param dest_mem Destination memory block pointer
|
|
* @param length Length of destination memory block
|
|
* @param version Wanted WOPN version
|
|
* @param force_gm Force GM set in saved bank file
|
|
* @return Error code or 0 on success
|
|
*/
|
|
extern int WOPN_SaveBankToMem(WOPNFile *file, void *dest_mem, size_t length, uint16_t version, uint16_t force_gm);
|
|
|
|
/**
|
|
* @brief Write raw WOPI into given memory block
|
|
* @param file Pointer to WOPI file data structure
|
|
* @param dest_mem Destination memory block pointer
|
|
* @param length Length of destination memory block
|
|
* @param version Wanted WOPI version
|
|
* @return Error code or 0 on success
|
|
*/
|
|
extern int WOPN_SaveInstToMem(OPNIFile *file, void *dest_mem, size_t length, uint16_t version);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* WOPN_FILE_H */
|