mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-15 15:02:34 +02:00
Remove dependency on libMAD (hurrah!)
This commit is contained in:
parent
4f60dcb663
commit
8e26431665
@ -84,7 +84,6 @@ endif()
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(Bullet REQUIRED)
|
||||
find_package(MAD REQUIRED)
|
||||
find_package(GLM REQUIRED)
|
||||
find_package(LibSndFile REQUIRED)
|
||||
find_package(FFmpeg REQUIRED)
|
||||
|
@ -19,8 +19,6 @@ set(RWENGINE_SOURCES
|
||||
src/ai/PlayerController.hpp
|
||||
src/ai/TrafficDirector.cpp
|
||||
src/ai/TrafficDirector.hpp
|
||||
src/audio/MADStream.cpp
|
||||
src/audio/MADStream.hpp
|
||||
src/audio/SoundManager.cpp
|
||||
src/audio/SoundManager.hpp
|
||||
src/audio/alCheck.cpp
|
||||
@ -143,7 +141,6 @@ endif()
|
||||
|
||||
target_link_libraries(rwengine
|
||||
rwlib
|
||||
${MAD_LIBRARY}
|
||||
${LIBSNDFILE_LIBRARY}
|
||||
${FFMPEG_LIBRARIES}
|
||||
${OPENAL_LIBRARY}
|
||||
@ -152,7 +149,6 @@ target_link_libraries(rwengine
|
||||
|
||||
include_directories(SYSTEM
|
||||
${BULLET_INCLUDE_DIR}
|
||||
${MAD_INCLUDE_DIR}
|
||||
${LIBSNDFILE_INCLUDE_DIR}
|
||||
${FFMPEG_INCLUDE_DIR}
|
||||
${OPENAL_INCLUDE_DIR}
|
||||
|
@ -1,171 +0,0 @@
|
||||
#include "audio/MADStream.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
||||
inline signed int MADStream::scale(mad_fixed_t sample) {
|
||||
/* round */
|
||||
sample += (1L << (MAD_F_FRACBITS - 16));
|
||||
|
||||
/* clip */
|
||||
if (sample >= MAD_F_ONE) {
|
||||
sample = MAD_F_ONE - 1;
|
||||
} else if (sample < -MAD_F_ONE) {
|
||||
sample = -MAD_F_ONE;
|
||||
}
|
||||
|
||||
/* quantize */
|
||||
return sample >> (MAD_F_FRACBITS + 1 - 16);
|
||||
}
|
||||
|
||||
mad_flow MADStream::ms_header(void* user, mad_header const* header) {
|
||||
MADStream* stream = static_cast<MADStream*>(user);
|
||||
|
||||
stream->mMadSampleRate = header->samplerate;
|
||||
// see enum mad_mode
|
||||
stream->mMadChannels = header->mode + 1;
|
||||
|
||||
return MAD_FLOW_CONTINUE;
|
||||
}
|
||||
|
||||
mad_flow MADStream::ms_input(void* user, mad_stream* stream) {
|
||||
MADStream* self = static_cast<MADStream*>(user);
|
||||
|
||||
if (!self->mReadProgress) {
|
||||
return MAD_FLOW_STOP;
|
||||
}
|
||||
|
||||
auto rd = self->mReadProgress;
|
||||
self->mReadProgress = 0;
|
||||
|
||||
mad_stream_buffer(stream, self->mFdm, rd);
|
||||
|
||||
return MAD_FLOW_CONTINUE;
|
||||
}
|
||||
|
||||
mad_flow MADStream::ms_output(void* user, mad_header const* header,
|
||||
mad_pcm* pcm) {
|
||||
RW_UNUSED(header);
|
||||
|
||||
MADStream* self = static_cast<MADStream*>(user);
|
||||
|
||||
if (self->stopped) {
|
||||
return MAD_FLOW_STOP;
|
||||
}
|
||||
|
||||
if (!self->numFreeBuffers) {
|
||||
ALint buffersProcessed;
|
||||
do {
|
||||
/**
|
||||
* Sleep a bit while waiting for OpenAL buffers to become available.
|
||||
* The number is arbitrary and depends on the size of the
|
||||
* buffer/audio samples,
|
||||
* as well as how quickly the computer can feed more buffers into
|
||||
* OpenAL.
|
||||
*/
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
alGetSourcei(self->alSource, AL_BUFFERS_PROCESSED,
|
||||
&buffersProcessed);
|
||||
} while (buffersProcessed <= 0);
|
||||
|
||||
alCheck(alSourceUnqueueBuffers(self->alSource, buffersProcessed,
|
||||
self->unqueuedBuffers));
|
||||
self->numFreeBuffers += buffersProcessed;
|
||||
}
|
||||
|
||||
int nsamples = pcm->length;
|
||||
mad_fixed_t const *left, *right;
|
||||
|
||||
left = pcm->samples[0];
|
||||
right = pcm->samples[1];
|
||||
|
||||
int s = 0;
|
||||
while (nsamples--) {
|
||||
signed int sample = *left++;
|
||||
self->mCurrentSamples.push_back(scale(sample));
|
||||
|
||||
sample = *right++;
|
||||
self->mCurrentSamples.push_back(scale(sample));
|
||||
s++;
|
||||
}
|
||||
|
||||
alCheck(alBufferData(self->buffers[self->currentBuffer], AL_FORMAT_STEREO16,
|
||||
self->mCurrentSamples.data(),
|
||||
self->mCurrentSamples.size() * sizeof(uint16_t),
|
||||
pcm->samplerate));
|
||||
alCheck(alSourceQueueBuffers(self->alSource, 1,
|
||||
self->buffers + self->currentBuffer));
|
||||
|
||||
self->mCurrentSamples.clear();
|
||||
self->currentBuffer++;
|
||||
self->currentBuffer %= numALbuffers;
|
||||
self->numFreeBuffers--;
|
||||
|
||||
return MAD_FLOW_CONTINUE;
|
||||
}
|
||||
|
||||
mad_flow MADStream::ms_error(void* user, mad_stream* stream, mad_frame* frame) {
|
||||
RW_UNUSED(user);
|
||||
RW_UNUSED(frame);
|
||||
|
||||
std::cerr << "libmad error: " << mad_stream_errorstr(stream) << std::endl;
|
||||
return MAD_FLOW_BREAK;
|
||||
}
|
||||
|
||||
MADStream::MADStream() : mFdm(nullptr) {
|
||||
alCheck(alGenBuffers(numALbuffers, buffers));
|
||||
alCheck(alGenSources(1, &alSource));
|
||||
}
|
||||
|
||||
MADStream::~MADStream() {
|
||||
if (mFdm) {
|
||||
munmap(mFdm, mStat.st_size);
|
||||
mad_decoder_finish(&mDecoder);
|
||||
}
|
||||
}
|
||||
|
||||
bool MADStream::openFromFile(const std::string& loc) {
|
||||
if (mFdm) {
|
||||
munmap(mFdm, mStat.st_size);
|
||||
mCurrentSamples.clear();
|
||||
mad_decoder_finish(&mDecoder);
|
||||
}
|
||||
|
||||
int fd = ::open(loc.c_str(), O_RDONLY);
|
||||
|
||||
if (fstat(fd, &mStat) == -1 || mStat.st_size == 0) {
|
||||
std::cerr << "Fstat failed (" << loc << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void* m = mmap(0, mStat.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (m == MAP_FAILED) {
|
||||
std::cerr << "mmap failed (" << loc << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mFdm = (unsigned char*)m;
|
||||
mReadProgress = mStat.st_size;
|
||||
|
||||
mad_decoder_init(&mDecoder, this, ms_input, ms_header, 0, ms_output,
|
||||
ms_error, 0);
|
||||
|
||||
new std::thread(
|
||||
[&]() { mad_decoder_run(&mDecoder, MAD_DECODER_MODE_SYNC); });
|
||||
|
||||
alCheck(alSourcef(alSource, AL_PITCH, 1));
|
||||
alCheck(alSourcef(alSource, AL_GAIN, 1));
|
||||
alCheck(alSource3f(alSource, AL_POSITION, 0, 0, 0));
|
||||
alCheck(alSource3f(alSource, AL_VELOCITY, 0, 0, 0));
|
||||
alCheck(alSourcei(alSource, AL_LOOPING, AL_FALSE));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MADStream::play() {
|
||||
alCheck(alSourcePlay(alSource));
|
||||
}
|
||||
|
||||
void MADStream::stop() {
|
||||
stopped = true;
|
||||
alCheck(alSourcePlay(alSource));
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef _MADSTREAM_HPP_
|
||||
#define _MADSTREAM_HPP_
|
||||
|
||||
#include "al.h"
|
||||
#include "alc.h"
|
||||
#include <fcntl.h>
|
||||
#include <mad.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <rw/defines.hpp>
|
||||
#include "audio/alCheck.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class MADStream {
|
||||
mad_decoder mDecoder;
|
||||
unsigned int mMadSampleRate;
|
||||
unsigned int mMadChannels;
|
||||
unsigned char* mFdm;
|
||||
struct stat mStat;
|
||||
unsigned int mReadProgress;
|
||||
std::vector<int16_t> mCurrentSamples;
|
||||
|
||||
/**
|
||||
* The number of OpenAL buffers is arbitrary, but due to the kind of small
|
||||
* buffer/audio sample size, we need a bunch of them so the computer can
|
||||
* keep up with filling them.
|
||||
*/
|
||||
constexpr static size_t numALbuffers = 8;
|
||||
ALuint buffers[numALbuffers];
|
||||
ALuint unqueuedBuffers[numALbuffers];
|
||||
size_t numFreeBuffers = numALbuffers;
|
||||
size_t currentBuffer = 0;
|
||||
ALuint alSource;
|
||||
|
||||
bool stopped = false;
|
||||
|
||||
static inline signed int scale(mad_fixed_t sample);
|
||||
static mad_flow ms_header(void* user, mad_header const* header);
|
||||
static mad_flow ms_input(void* user, mad_stream* stream);
|
||||
static mad_flow ms_output(void* user, mad_header const* header,
|
||||
mad_pcm* pcm);
|
||||
static mad_flow ms_error(void* user, mad_stream* stream, mad_frame* frame);
|
||||
|
||||
public:
|
||||
MADStream();
|
||||
~MADStream();
|
||||
|
||||
bool openFromFile(const std::string& loc);
|
||||
void play();
|
||||
void stop();
|
||||
};
|
||||
|
||||
#endif
|
@ -1,7 +1,5 @@
|
||||
#include <audio/MADStream.hpp>
|
||||
#include <audio/SoundManager.hpp>
|
||||
|
||||
#include "audio/MADStream.hpp"
|
||||
#include "audio/alCheck.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class MADStream;
|
||||
|
||||
class SoundManager {
|
||||
public:
|
||||
SoundManager();
|
||||
|
@ -17,7 +17,6 @@ class Logger;
|
||||
#include <objects/VehicleInfo.hpp>
|
||||
#include <rw/types.hpp>
|
||||
|
||||
#include <audio/MADStream.hpp>
|
||||
#include <gl/TextureData.hpp>
|
||||
#include <platform/FileIndex.hpp>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user