Skip to content

Commit

Permalink
add sound support
Browse files Browse the repository at this point in the history
  • Loading branch information
qnnnnez committed Jan 11, 2017
1 parent 0a7b9db commit 72591a9
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 7 deletions.
83 changes: 79 additions & 4 deletions process.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "process.h"
#include "native.h"
#include "wav.h"
#include <stdexcept>
#include <set>
#include <vector>
Expand All @@ -17,7 +18,7 @@ namespace scpak
{
const char *PakInfoFileName = "scpak.meta";

void unpack(const PakFile &pak, const std::string &dirPath, bool unpackText, bool unpackTexture, bool unpackFont)
void unpack(const PakFile &pak, const std::string &dirPath, bool unpackText, bool unpackTexture, bool unpackFont, bool unpackSound)
{
std::string dirPathSafe = dirPath;
if (*dirPathSafe.rbegin() != pathsep)
Expand Down Expand Up @@ -73,6 +74,10 @@ namespace scpak
{
unpack_bitmapFont(dirPathSafe, item);
}
else if (unpackSound && itemType == "Engine.Audio.SoundBuffer")
{
unpack_soundBuffer(dirPathSafe, item);
}
else
{
unpack_raw:
Expand All @@ -90,7 +95,7 @@ namespace scpak
fout.close();
}

PakFile pack(const std::string &dirPath, bool packText, bool packTexture, bool packFont)
PakFile pack(const std::string &dirPath, bool packText, bool packTexture, bool packFont, bool packSound)
{
PakFile pak;
std::vector<PakItem> contents = pak.contents();
Expand Down Expand Up @@ -166,6 +171,10 @@ namespace scpak
{
pack_bitmapFont(dirPathSafe, item);
}
else if (packSound && type == "Engine.Audio.SoundBuffer")
{
pack_soundBuffer(dirPathSafe, item);
}
else
{
pack_raw:
Expand Down Expand Up @@ -411,9 +420,75 @@ namespace scpak
stbi_image_free(data);
}

bool isPowerOfTwo(int n)
void unpack_soundBuffer(const std::string &outputDir, const PakItem &item)
{
static const int bitsPerSample = 16;

MemoryBinaryReader reader(item.data.data());

bool oggCompressed = reader.readBoolean();

if (!oggCompressed)
{
std::string listFileName = outputDir + item.name + ".wav";
WavHeader header;
WavHeader::SetMagicValues(header);
header.channelCount = reader.readInt();
header.sampleRate = reader.readInt();
header.subchunk2Size = reader.readInt();

header.bitsPerSample = bitsPerSample;
header.byteRate = header.sampleRate * bitsPerSample / 8;
header.chunkSize = header.subchunk2Size + 36;

const byte *sound = item.data.data() + reader.position;
std::ofstream fout(listFileName, std::ios::binary);
fout.write(reinterpret_cast<const char*>(&header), sizeof(header));
fout.write(reinterpret_cast<const char*>(sound), header.subchunk2Size);
fout.close();
}
else
{
std::ofstream(outputDir + item.name, std::ios::binary).write(reinterpret_cast<const char*>(item.data.data()), item.data.size());
}
}

void pack_soundBuffer(const std::string &inputDir, PakItem &item)
{
return (n & (n - 1)) == 0;
std::string inputFilePathBase = inputDir + item.name;
if (pathExists(inputFilePathBase.c_str()))
{
int fileSize = getFileSize(inputFilePathBase.c_str());
std::ifstream file(inputFilePathBase, std::ios::binary);
item.data.resize(fileSize);
item.length = fileSize;
file.read(reinterpret_cast<char*>(item.data.data()), fileSize);
file.close();
}
else if (pathExists((inputFilePathBase + ".wav").c_str()))
{
static const int bitsPerSample = 16;

std::string fileName = inputFilePathBase + ".wav";
std::ifstream fin(fileName, std::ios::binary);
WavHeader header;
fin.read(reinterpret_cast<char*>(&header), sizeof(header));
item.data.resize(header.subchunk2Size + 13);
MemoryBinaryWriter writer(item.data.data());
writer.writeBoolean(false);
writer.writeInt(header.channelCount);
writer.writeInt(header.sampleRate);
writer.writeInt(header.subchunk2Size);

if (header.bitsPerSample != 16)
{
throw std::runtime_error("WAV-" + fileName + ": bitsPerSample must be 16.");
}

fin.read(reinterpret_cast<char*>(item.data.data() + writer.position), header.subchunk2Size);
fin.close();
item.length = item.data.size();
}
}
}

9 changes: 6 additions & 3 deletions process.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
namespace scpak
{
PakFile pack(const std::string &dirPath,
bool packText=true, bool packTexture=true, bool packFont=true);
bool packText=true, bool packTexture=true, bool packFont=true,
bool packSound=true);
void unpack(const PakFile &pak, const std::string &dirPath,
bool unpackText=true, bool unpackTexture=true, bool unpackFont=true);
bool unpackText=true, bool unpackTexture=true, bool unpackFont=true,
bool unpackSound=true);

int calcMipmapSize(int width, int height, int level=0);
int generateMipmap(int width, int height, int level, unsigned char *image);
Expand All @@ -18,7 +20,8 @@ namespace scpak
void unpack_bitmapFont(const std::string &outputDir, const PakItem &item);
void pack_bitmapFont(const std::string &inputDir, PakItem &item);

bool isPowerOfTwo(int number);
void unpack_soundBuffer(const std::string &outputDir, const PakItem &item);
void pack_soundBuffer(const std::string &inputDir, PakItem &item);

struct Vector2f
{
Expand Down
12 changes: 12 additions & 0 deletions wav.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "wav.h"

namespace scpak
{
const std::string WavHeader::chunkIdMagic = "RIFF";
const std::string WavHeader::formatMagic = "WAVE";
const std::string WavHeader::subchunk1LabelMagic = "fmt ";
const std::uint32_t WavHeader::subchunk1SizeMagic = 16;
const std::uint16_t WavHeader::audioFormatMagic = 1;
const std::uint16_t WavHeader::blockAlighMagic = 4;
const std::string WavHeader::subchunk2LabelMagic = "data";
}
68 changes: 68 additions & 0 deletions wav.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#pragma once
#include <vector>
#include <string>
#include <algorithm>

#include "scpak.h"
#include "binaryio.h"


namespace scpak
{
typedef struct WavHeaderStruct
{
char chunkId[4]; // "RIFF"
std::uint32_t chunkSize;
char format[4]; // "WAVE"

char subchunk1Label[4]; // "fmt "
std::uint32_t subchunk1Size; // 16
std::uint16_t audioFormat; // 1 - PCM
std::uint16_t channelCount;
std::uint32_t sampleRate;
std::uint32_t byteRate; // per channel
std::uint16_t blockAlign; // 4
std::uint16_t bitsPerSample;

char subchunk2Label[4]; // "data"
std::uint32_t subchunk2Size; // second * byte_rate * channel_count


static const std::string chunkIdMagic;
static const std::string formatMagic;
static const std::string subchunk1LabelMagic;
static const std::uint32_t subchunk1SizeMagic;
static const std::uint16_t audioFormatMagic;
static const std::uint16_t blockAlighMagic;
static const std::string subchunk2LabelMagic;

bool checkMagicValues() const
{
return
chunkSize == subchunk2Size + 36 &&
chunkId == chunkIdMagic &&
format == formatMagic &&
subchunk1Label == subchunk1LabelMagic &&
subchunk1Size == subchunk1SizeMagic &&
audioFormat == audioFormatMagic &&
blockAlign == blockAlighMagic &&
subchunk2Label == subchunk2LabelMagic;
}

static void SetMagicValues(struct WavHeaderStruct &header)
{
auto copyString = [](std::string src, char *dst)
{
std::copy(src.begin(), src.end(), dst);
};

copyString(chunkIdMagic, header.chunkId);
copyString(formatMagic, header.format);
copyString(subchunk1LabelMagic, header.subchunk1Label);
header.subchunk1Size = subchunk1SizeMagic;
header.audioFormat = audioFormatMagic;
header.blockAlign = blockAlighMagic;
copyString(subchunk2LabelMagic, header.subchunk2Label);
}
} WavHeader;
}

0 comments on commit 72591a9

Please sign in to comment.