Added "force mono" option to Music and SoundBuffer

Former-commit-id: 1f46d1461a8289a590a71e368f282a955d7d8234
This commit is contained in:
Lynix 2014-01-10 20:09:13 +01:00
parent faed82426f
commit d902eea49e
5 changed files with 87 additions and 8 deletions

View File

@ -0,0 +1,16 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Audio module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_ALGORITHM_AUDIO_HPP
#define NAZARA_ALGORITHM_AUDIO_HPP
#include <Nazara/Prerequesites.hpp>
template<typename T> void NzMixToMono(T* input, T* output, unsigned int channelCount, unsigned int frameCount);
#include <Nazara/Audio/Algorithm.inl>
#endif // NAZARA_ALGORITHM_AUDIO_HPP

View File

@ -0,0 +1,25 @@
// Copyright (C) 2013 Jérôme Leclercq
// This file is part of the "Nazara Engine - Audio module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <Nazara/Audio/Debug.hpp>
template<typename T>
void NzMixToMono(T* input, T* output, unsigned int channelCount, unsigned int frameCount)
{
// Pour éviter l'overflow, on utilise comme accumulateur un type assez grand, (u)int 64 bits pour les entiers, double pour les flottants
typedef typename std::conditional<std::is_unsigned<T>::value, nzUInt64, nzInt64>::type BiggestInt;
typedef typename std::conditional<std::is_integral<T>::value, BiggestInt, double>::type Biggest;
for (unsigned int i = 0; i < frameCount; ++i)
{
Biggest acc = Biggest(0);
for (unsigned int j = 0; j < channelCount; ++j)
acc += input[i*channelCount + j];
output[i] = acc/channelCount;
}
}
#include <Nazara/Audio/DebugOff.hpp>

View File

@ -14,6 +14,8 @@
struct NzMusicParams
{
bool forceMono = false;
bool IsValid() const;
};

View File

@ -17,6 +17,8 @@
struct NzSoundBufferParams
{
bool forceMono = false;
bool IsValid() const;
};

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Audio/Loaders/sndfile.hpp>
#include <Nazara/Audio/Algorithm.hpp>
#include <Nazara/Audio/Audio.hpp>
#include <Nazara/Audio/Config.hpp>
#include <Nazara/Audio/Music.hpp>
@ -89,6 +90,9 @@ namespace
nzAudioFormat GetFormat() const
{
if (m_mixToMono)
return nzAudioFormat_Mono;
else
return m_format;
}
@ -102,7 +106,7 @@ namespace
return m_sampleRate;
}
bool Open(const NzString& filePath)
bool Open(const NzString& filePath, bool forceMono)
{
m_file = new NzFile(filePath);
if (!m_file->Open(NzFile::ReadOnly))
@ -111,12 +115,14 @@ namespace
return false;
}
return Open(*m_file);
return Open(*m_file, forceMono);
}
bool Open(NzInputStream& stream)
bool Open(NzInputStream& stream, bool forceMono)
{
SF_INFO infos;
infos.format = 0;
m_handle = sf_open_virtual(&callbacks, SFM_READ, &infos, &stream);
if (!m_handle)
{
@ -127,10 +133,10 @@ namespace
m_format = NzAudio::GetAudioFormat(infos.channels);
if (m_format == nzAudioFormat_Unknown)
{
NazaraError("Channel count not handled");
sf_close(m_handle);
m_handle = nullptr;
NazaraError("Channel count not handled");
return false;
}
@ -145,11 +151,28 @@ namespace
if (infos.format & SF_FORMAT_VORBIS)
sf_command(m_handle, SFC_SET_SCALE_FLOAT_INT_READ, nullptr, SF_TRUE);
if (forceMono && m_format != nzAudioFormat_Mono)
{
m_mixToMono = true;
m_sampleCount = infos.frames;
}
else
m_mixToMono = false;
return true;
}
unsigned int Read(void* buffer, unsigned int sampleCount)
{
if (m_mixToMono)
{
std::unique_ptr<nzInt16[]> samples(new nzInt16[m_format*sampleCount]);
unsigned int readSampleCount = sf_read_short(m_handle, samples.get(), m_format*sampleCount);
NzMixToMono(samples.get(), reinterpret_cast<nzInt16*>(buffer), m_format, sampleCount);
return readSampleCount / m_format;
}
else
return sf_read_short(m_handle, reinterpret_cast<nzInt16*>(buffer), sampleCount);
}
@ -162,6 +185,7 @@ namespace
nzAudioFormat m_format;
NzFile* m_file;
SNDFILE* m_handle;
bool m_mixToMono;
unsigned int m_duration;
unsigned int m_sampleCount;
unsigned int m_sampleRate;
@ -199,7 +223,7 @@ namespace
NazaraUnused(parameters);
std::unique_ptr<sndfileStream> musicStream(new sndfileStream);
if (!musicStream->Open(filePath))
if (!musicStream->Open(filePath, parameters.forceMono))
{
NazaraError("Failed to open music stream");
return false;
@ -221,7 +245,7 @@ namespace
NazaraUnused(parameters);
std::unique_ptr<sndfileStream> musicStream(new sndfileStream);
if (!musicStream->Open(stream))
if (!musicStream->Open(stream, parameters.forceMono))
{
NazaraError("Failed to open music stream");
return false;
@ -295,6 +319,16 @@ namespace
return false;
}
if (parameters.forceMono && format != nzAudioFormat_Mono)
{
std::unique_ptr<nzInt16[]> monoSamples(new nzInt16[info.frames]);
NzMixToMono(samples.get(), monoSamples.get(), info.channels, info.frames);
format = nzAudioFormat_Mono;
samples = std::move(monoSamples);
sampleCount = info.frames;
}
if (!soundBuffer->Create(format, static_cast<unsigned int>(sampleCount), info.samplerate, samples.get()))
{
sf_close(file);