Skip to content

Commit

Permalink
Support Kinc's separate audio channels
Browse files Browse the repository at this point in the history
  • Loading branch information
RobDangerous committed Jan 30, 2024
1 parent 00a80e0 commit a94956b
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 95 deletions.
46 changes: 28 additions & 18 deletions Sources/Kore/Audio1/Audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ namespace {
}*/
}

void Audio1::mix(int samples) {
for (int i = 0; i < samples; ++i) {
bool left = (i % 2) == 0;
float value = 0;
void Audio1::mix(uint32_t samples) {
for (uint32_t i = 0; i < samples; ++i) {
float leftValue = 0;
float rightValue = 0;
#if 0
__m128 sseSamples[4];
for (int i = 0; i < channelCount; i += 4) {
Expand All @@ -74,12 +74,11 @@ void Audio1::mix(int samples) {
for (int i = 0; i < channelCount; ++i) {
if (channels[i].sound != nullptr) {
// value += *(s16*)&channels[i].sound->data[(int)channels[i].position] / 32767.0f * channels[i].sound->volume();
if (left)
value += sampleLinear(channels[i].sound->left, channels[i].position) * channels[i].volume * channels[i].sound->volume();
else
value += sampleLinear(channels[i].sound->right, channels[i].position) * channels[i].volume * channels[i].sound->volume();
value = max(min(value, 1.0f), -1.0f);
if (!left) channels[i].position += channels[i].pitch / channels[i].sound->sampleRatePos;
leftValue += sampleLinear(channels[i].sound->left, channels[i].position) * channels[i].volume * channels[i].sound->volume();
leftValue = max(min(leftValue, 1.0f), -1.0f);
rightValue += sampleLinear(channels[i].sound->right, channels[i].position) * channels[i].volume * channels[i].sound->volume();
rightValue = max(min(rightValue, 1.0f), -1.0f);
channels[i].position += channels[i].pitch / channels[i].sound->sampleRatePos;
// channels[i].position += 2;
if (channels[i].position + 1 >= channels[i].sound->size) {
if (channels[i].loop) {
Expand All @@ -93,25 +92,36 @@ void Audio1::mix(int samples) {
}
for (int i = 0; i < channelCount; ++i) {
if (streams[i].stream != nullptr) {
value += streams[i].stream->nextSample() * streams[i].stream->volume();
value = max(min(value, 1.0f), -1.0f);
if (streams[i].stream->ended()) streams[i].stream = nullptr;
float *samples = streams[i].stream->nextFrame();
leftValue += samples[0] * streams[i].stream->volume();
leftValue = max(min(leftValue, 1.0f), -1.0f);
rightValue += samples[1] * streams[i].stream->volume();
rightValue = max(min(rightValue, 1.0f), -1.0f);
if (streams[i].stream->ended()) {
streams[i].stream = nullptr;
}
}
}
for (int i = 0; i < channelCount; ++i) {
if (videos[i].stream != nullptr) {
value += kinc_internal_video_sound_stream_next_sample(videos[i].stream);
value = max(min(value, 1.0f), -1.0f);
float *samples = kinc_internal_video_sound_stream_next_frame(videos[i].stream);
leftValue += samples[0];
leftValue = max(min(leftValue, 1.0f), -1.0f);
rightValue += samples[1];
rightValue = max(min(rightValue, 1.0f), -1.0f);
if (kinc_internal_video_sound_stream_ended(videos[i].stream)) {
videos[i].stream = nullptr;
}
}
}
mutex.unlock();
#endif
*(float *)&Audio2::buffer.data[Audio2::buffer.writeLocation] = value;
Audio2::buffer.writeLocation += 4;
if (Audio2::buffer.writeLocation >= Audio2::buffer.dataSize) Audio2::buffer.writeLocation = 0;
Audio2::buffer.channels[0][Audio2::buffer.writeLocation] = leftValue;
Audio2::buffer.channels[1][Audio2::buffer.writeLocation] = rightValue;
Audio2::buffer.writeLocation += 1;
if (Audio2::buffer.writeLocation >= Audio2::buffer.dataSize) {
Audio2::buffer.writeLocation = 0;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Kore/Audio1/Audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ namespace Kore {
void stop(SoundStream *stream);
void play(kinc_internal_video_sound_stream *stream);
void stop(kinc_internal_video_sound_stream *stream);
void mix(int samples);
void mix(uint32_t samples);
}
}
8 changes: 7 additions & 1 deletion Sources/Kore/Audio1/Sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
#include <Kore/IO/Reader.h>

namespace Kore {
struct BufferFormat {
int channels;
int samplesPerSecond;
int bitsPerSample;
};

struct Sound {
public:
Sound(const char *filename);
Sound(Reader &file, const char *filename);
~Sound();
void load(Reader &file, const char *filename);
Audio2::BufferFormat format;
BufferFormat format;
float volume();
void setVolume(float value);
s16 *left;
Expand Down
61 changes: 28 additions & 33 deletions Sources/Kore/Audio1/SoundStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

using namespace Kore;

SoundStream::SoundStream(const char *filename, bool looping) : myLooping(looping), myVolume(1), decoded(false), rateDecodedHack(false), end(false) {
SoundStream::SoundStream(const char *filename, bool looping) : myLooping(looping), myVolume(1), rateDecodedHack(false), end(false) {
FileReader file(filename);
buffer = new u8[file.size()];
u8 *filecontent = (u8 *)file.readAll();
Expand Down Expand Up @@ -66,47 +66,42 @@ void SoundStream::reset() {
if (vorbis != nullptr) stb_vorbis_seek_start(vorbis);
end = false;
rateDecodedHack = false;
decoded = false;
}

float SoundStream::nextSample() {
if (vorbis == nullptr) return 0;
float *SoundStream::nextFrame() {
if (vorbis == nullptr) {
for (int i = 0; i < chans; ++i) {
samples[i] = 0;
}
return samples;
}
if (rate == 22050) {
if (rateDecodedHack) {
if (decoded) {
decoded = false;
return samples[0];
}
else {
rateDecodedHack = false;
decoded = true;
return samples[1];
}
rateDecodedHack = false;
return samples;
}
}
if (decoded) {
decoded = false;
if (chans == 1) {
return samples[0];

float left, right;
float *samplesArray[2] = {&left, &right};
int read = stb_vorbis_get_samples_float(vorbis, chans, samplesArray, 1);
if (read == 0) {
if (looping()) {
stb_vorbis_seek_start(vorbis);
stb_vorbis_get_samples_float(vorbis, chans, samplesArray, 1);
}
else {
return samples[1];
}
}
else {
int read = stb_vorbis_get_samples_float_interleaved(vorbis, chans, &samples[0], chans);
if (read == 0) {
if (looping()) {
stb_vorbis_seek_start(vorbis);
stb_vorbis_get_samples_float_interleaved(vorbis, chans, &samples[0], chans);
}
else {
end = true;
return 0.0f;
end = true;
for (int i = 0; i < chans; ++i) {
samples[i] = 0;
}
return samples;
}
decoded = true;
rateDecodedHack = true;
return samples[0];
}

samples[0] = samplesArray[0][0];
samples[1] = samplesArray[1][0];

rateDecodedHack = true;
return samples;
}
3 changes: 1 addition & 2 deletions Sources/Kore/Audio1/SoundStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Kore {
class SoundStream {
public:
SoundStream(const char *filename, bool looping);
float nextSample();
float *nextFrame();
int channels();
int sampleRate();
bool looping();
Expand All @@ -26,7 +26,6 @@ namespace Kore {
int rate;
bool myLooping;
float myVolume;
bool decoded;
bool rateDecodedHack;
bool end;
float samples[2];
Expand Down
46 changes: 21 additions & 25 deletions Sources/Kore/Audio2/Audio.cpp
Original file line number Diff line number Diff line change
@@ -1,62 +1,54 @@
#include "Audio.h"

#include <kinc/audio2/audio.h>

#include <stdio.h>

using namespace Kore;

void (*Audio2::audioCallback)(int samples) = nullptr;
void (*Audio2::audioCallback)(uint32_t samples) = nullptr;
Audio2::Buffer Audio2::buffer;
int Audio2::samplesPerSecond = 44100;

namespace {
void audio(kinc_a2_buffer_t *buffer, int samples) {
void audio(kinc_a2_buffer_t *buffer, uint32_t samples, void *userdata) {
if (Audio2::audioCallback != nullptr) {
Audio2::audioCallback(samples);
}
else {
for (int i = 0; i < samples; ++i) {
*(float *)&Audio2::buffer.data[Audio2::buffer.writeLocation] = 0.0f;
Audio2::buffer.writeLocation += 4;
for (uint32_t i = 0; i < samples; ++i) {
Audio2::buffer.channels[0][Audio2::buffer.writeLocation] = 0.0f;
Audio2::buffer.channels[1][Audio2::buffer.writeLocation] = 0.0f;
Audio2::buffer.writeLocation += 1;
if (Audio2::buffer.writeLocation >= Audio2::buffer.dataSize) {
Audio2::buffer.writeLocation = 0;
}
}
}
for (int i = 0; i < samples; ++i) {
float sample = *(float *)&Audio2::buffer.data[Audio2::buffer.readLocation];
Audio2::buffer.readLocation += 4;
for (uint32_t i = 0; i < samples; ++i) {
float leftSample = Audio2::buffer.channels[0][Audio2::buffer.readLocation];
float rightSample = Audio2::buffer.channels[1][Audio2::buffer.readLocation];
Audio2::buffer.readLocation += 1;
if (Audio2::buffer.readLocation >= Audio2::buffer.dataSize) {
Audio2::buffer.readLocation = 0;
}

*(float *)&buffer->data[buffer->write_location] = sample;
buffer->write_location += 4;
buffer->channels[0][buffer->write_location] = leftSample;
buffer->channels[1][buffer->write_location] = rightSample;
buffer->write_location += 1;
if (buffer->write_location >= buffer->data_size) {
buffer->write_location = 0;
}
}
}

#if defined(KORE_IOS) || defined(KORE_MACOS)
void sample_rate_changed() {
Audio2::samplesPerSecond = kinc_a2_samples_per_second;
}
#endif
}

void Audio2::init() {
kinc_a2_init();
buffer.readLocation = 0;
buffer.writeLocation = 0;
buffer.dataSize = 128 * 1024;
buffer.data = new u8[buffer.dataSize];
Audio2::samplesPerSecond = kinc_a2_samples_per_second;
kinc_a2_set_callback(audio);
#if defined(KORE_IOS) || defined(KORE_MACOS)
kinc_a2_set_sample_rate_callback(sample_rate_changed);
#endif
buffer.channelCount = 2;
buffer.channels[0] = new float[buffer.dataSize];
buffer.channels[1] = new float[buffer.dataSize];
kinc_a2_set_callback(audio, nullptr);
}

void Audio2::update() {
Expand All @@ -66,3 +58,7 @@ void Audio2::update() {
void Audio2::shutdown() {
kinc_a2_shutdown();
}

uint32_t Audio2::samplesPerSecond() {
return kinc_a2_samples_per_second();
}
23 changes: 9 additions & 14 deletions Sources/Kore/Audio2/Audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,23 @@

#include <Kore/global.h>

#include <kinc/audio2/audio.h>

namespace Kore {
namespace Audio2 {
void init();
void update();
void shutdown();
uint32_t samplesPerSecond();

extern int samplesPerSecond;

extern void (*audioCallback)(int samples);

struct BufferFormat {
int channels;
int samplesPerSecond;
int bitsPerSample;
};
extern void (*audioCallback)(uint32_t samples);

struct Buffer {
BufferFormat format;
u8 *data;
int dataSize;
int readLocation;
int writeLocation;
uint8_t channelCount;
float *channels[KINC_A2_MAX_CHANNELS];
uint32_t dataSize;
uint32_t readLocation;
uint32_t writeLocation;
};

extern Buffer buffer;
Expand Down

0 comments on commit a94956b

Please sign in to comment.