mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 20:58:07 +03:00
audio: split into smaller functions
This commit is contained in:
parent
e439371c66
commit
3696e84925
3 changed files with 140 additions and 129 deletions
|
@ -39,6 +39,7 @@
|
||||||
- fixed Story So Far not playing the opening FMV, `cafe.rpl` (#2779, regression from 2.10)
|
- fixed Story So Far not playing the opening FMV, `cafe.rpl` (#2779, regression from 2.10)
|
||||||
- fixed Lara at times ending up in incorrect rooms when using the teleport cheat (#2486, regression from 3.0)
|
- fixed Lara at times ending up in incorrect rooms when using the teleport cheat (#2486, regression from 3.0)
|
||||||
- fixed the `/pos` console command reporting the base room number when Lara is actually in a flipped room (#2487, regression from 3.0)
|
- fixed the `/pos` console command reporting the base room number when Lara is actually in a flipped room (#2487, regression from 3.0)
|
||||||
|
- fixed clicks in audio sounds (#2846, regression from 2.0)
|
||||||
- improved bubble appearance (#2672)
|
- improved bubble appearance (#2672)
|
||||||
- improved rendering performance
|
- improved rendering performance
|
||||||
- improved pause exit dialog - it can now be canceled with escape
|
- improved pause exit dialog - it can now be canceled with escape
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
- fixed guns carried by enemies not being converted to ammo if Lara has picked up the same gun elsewhere in the same level (#2856)
|
- fixed guns carried by enemies not being converted to ammo if Lara has picked up the same gun elsewhere in the same level (#2856)
|
||||||
- fixed guns carried by enemies not being converted to ammo if Lara starts the level with the gun and the game has later been reloaded (#2850, regression from 1.0)
|
- fixed guns carried by enemies not being converted to ammo if Lara starts the level with the gun and the game has later been reloaded (#2850, regression from 1.0)
|
||||||
- fixed 1920x1080 screenshots in 16:9 aspect mode being saved as 1919x1080 (#2845, regression from 0.8)
|
- fixed 1920x1080 screenshots in 16:9 aspect mode being saved as 1919x1080 (#2845, regression from 0.8)
|
||||||
|
- fixed clicks in audio sounds (#2846, regression from 0.2)
|
||||||
|
|
||||||
## [1.0.1](https://github.com/LostArtefacts/TRX/compare/tr2-1.0...tr2-1.0.1) - 2025-04-24
|
## [1.0.1](https://github.com/LostArtefacts/TRX/compare/tr2-1.0...tr2-1.0.1) - 2025-04-24
|
||||||
- added an option to wraparound when scrolling UI dialogs, such as save/load (#2834)
|
- added an option to wraparound when scrolling UI dialogs, such as save/load (#2834)
|
||||||
|
|
|
@ -23,10 +23,20 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
int32_t format;
|
||||||
|
AVChannelLayout ch_layout;
|
||||||
|
int32_t sample_rate;
|
||||||
|
} src, dst;
|
||||||
|
SwrContext *ctx;
|
||||||
|
size_t working_buffer_size;
|
||||||
|
uint8_t *working_buffer;
|
||||||
|
} M_SWR_CONTEXT;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *original_data;
|
char *original_data;
|
||||||
size_t original_size;
|
size_t original_size;
|
||||||
|
|
||||||
float *sample_data;
|
float *sample_data;
|
||||||
int32_t channels;
|
int32_t channels;
|
||||||
int32_t num_samples;
|
int32_t num_samples;
|
||||||
|
@ -135,6 +145,76 @@ static int64_t M_SeekAVBuffer(void *opaque, int64_t offset, int32_t whence)
|
||||||
return src->ptr - src->data;
|
return src->ptr - src->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t M_OutputAudioFrame(
|
||||||
|
M_SWR_CONTEXT *const swr, AVFrame *const frame)
|
||||||
|
{
|
||||||
|
uint8_t *out_buffer = nullptr;
|
||||||
|
const int32_t out_samples =
|
||||||
|
swr_get_out_samples(swr->ctx, frame->nb_samples);
|
||||||
|
av_samples_alloc(
|
||||||
|
&out_buffer, nullptr, swr->dst.ch_layout.nb_channels, out_samples,
|
||||||
|
swr->dst.format, 1);
|
||||||
|
int32_t resampled_size = swr_convert(
|
||||||
|
swr->ctx, &out_buffer, out_samples, (const uint8_t **)frame->data,
|
||||||
|
frame->nb_samples);
|
||||||
|
while (resampled_size > 0) {
|
||||||
|
int32_t out_buffer_size = av_samples_get_buffer_size(
|
||||||
|
nullptr, swr->dst.ch_layout.nb_channels, resampled_size,
|
||||||
|
swr->dst.format, 1);
|
||||||
|
|
||||||
|
if (out_buffer_size > 0) {
|
||||||
|
swr->working_buffer = Memory_Realloc(
|
||||||
|
swr->working_buffer,
|
||||||
|
swr->working_buffer_size + out_buffer_size);
|
||||||
|
if (out_buffer) {
|
||||||
|
memcpy(
|
||||||
|
swr->working_buffer + swr->working_buffer_size, out_buffer,
|
||||||
|
out_buffer_size);
|
||||||
|
}
|
||||||
|
swr->working_buffer_size += out_buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
resampled_size =
|
||||||
|
swr_convert(swr->ctx, &out_buffer, out_samples, nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
av_freep(&out_buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t M_DecodePacket(
|
||||||
|
AVCodecContext *const dec, const AVPacket *const pkt, AVFrame *frame,
|
||||||
|
M_SWR_CONTEXT *const swr)
|
||||||
|
{
|
||||||
|
// Submit the packet to the decoder
|
||||||
|
int32_t ret = avcodec_send_packet(dec, pkt);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERROR(
|
||||||
|
"Error submitting a packet for decoding (%s)\n", av_err2str(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all the available frames from the decoder
|
||||||
|
while (ret >= 0) {
|
||||||
|
ret = avcodec_receive_frame(dec, frame);
|
||||||
|
if (ret < 0) {
|
||||||
|
// those two return values are special and mean there is no output
|
||||||
|
// frame available, but there were no errors during decoding
|
||||||
|
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LOG_ERROR(
|
||||||
|
"Error receiving a frame for decoding (%s)\n", av_err2str(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = M_OutputAudioFrame(swr, frame);
|
||||||
|
av_frame_unref(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static bool M_ConvertRawData(
|
static bool M_ConvertRawData(
|
||||||
const uint8_t *const original_data, const int32_t original_size,
|
const uint8_t *const original_data, const int32_t original_size,
|
||||||
const int32_t dst_sample_rate, const int32_t dst_format,
|
const int32_t dst_sample_rate, const int32_t dst_format,
|
||||||
|
@ -142,8 +222,6 @@ static bool M_ConvertRawData(
|
||||||
size_t *const out_size, size_t *const out_sample_count)
|
size_t *const out_size, size_t *const out_sample_count)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
size_t working_buffer_size = 0;
|
|
||||||
float *working_buffer = nullptr;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
size_t read_buffer_size;
|
size_t read_buffer_size;
|
||||||
|
@ -165,19 +243,11 @@ static bool M_ConvertRawData(
|
||||||
.frame = nullptr,
|
.frame = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
M_SWR_CONTEXT swr = {};
|
||||||
struct {
|
|
||||||
int32_t format;
|
|
||||||
AVChannelLayout ch_layout;
|
|
||||||
int32_t sample_rate;
|
|
||||||
} src, dst;
|
|
||||||
SwrContext *ctx;
|
|
||||||
} swr = {};
|
|
||||||
|
|
||||||
int32_t error_code;
|
int32_t error_code;
|
||||||
|
|
||||||
unsigned char *read_buffer = av_malloc(av.read_buffer_size);
|
uint8_t *const read_buffer = av_malloc(av.read_buffer_size);
|
||||||
if (!read_buffer) {
|
if (read_buffer == nullptr) {
|
||||||
error_code = AVERROR(ENOMEM);
|
error_code = AVERROR(ENOMEM);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -195,8 +265,7 @@ static bool M_ConvertRawData(
|
||||||
|
|
||||||
av.format_ctx = avformat_alloc_context();
|
av.format_ctx = avformat_alloc_context();
|
||||||
av.format_ctx->pb = av.avio_context;
|
av.format_ctx->pb = av.avio_context;
|
||||||
error_code =
|
error_code = avformat_open_input(&av.format_ctx, "mem:", nullptr, nullptr);
|
||||||
avformat_open_input(&av.format_ctx, "dummy_filename", nullptr, nullptr);
|
|
||||||
if (error_code != 0) {
|
if (error_code != 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -214,19 +283,19 @@ static bool M_ConvertRawData(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!av.stream) {
|
if (av.stream == nullptr) {
|
||||||
error_code = AVERROR_STREAM_NOT_FOUND;
|
error_code = AVERROR_STREAM_NOT_FOUND;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
av.codec = avcodec_find_decoder(av.stream->codecpar->codec_id);
|
av.codec = avcodec_find_decoder(av.stream->codecpar->codec_id);
|
||||||
if (!av.codec) {
|
if (av.codec == nullptr) {
|
||||||
error_code = AVERROR_DEMUXER_NOT_FOUND;
|
error_code = AVERROR_DEMUXER_NOT_FOUND;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
av.codec_ctx = avcodec_alloc_context3(av.codec);
|
av.codec_ctx = avcodec_alloc_context3(av.codec);
|
||||||
if (!av.codec_ctx) {
|
if (av.codec_ctx == nullptr) {
|
||||||
error_code = AVERROR(ENOMEM);
|
error_code = AVERROR(ENOMEM);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -249,115 +318,62 @@ static bool M_ConvertRawData(
|
||||||
}
|
}
|
||||||
|
|
||||||
av.frame = av_frame_alloc();
|
av.frame = av_frame_alloc();
|
||||||
if (!av.frame) {
|
if (av.frame == nullptr) {
|
||||||
error_code = AVERROR(ENOMEM);
|
error_code = AVERROR(ENOMEM);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
swr.src.sample_rate = av.codec_ctx->sample_rate;
|
||||||
error_code = av_read_frame(av.format_ctx, av.packet);
|
swr.src.ch_layout = av.codec_ctx->ch_layout;
|
||||||
if (error_code == AVERROR_EOF) {
|
swr.src.format = av.codec_ctx->sample_fmt;
|
||||||
av_packet_unref(av.packet);
|
swr.dst.sample_rate = AUDIO_WORKING_RATE;
|
||||||
error_code = 0;
|
av_channel_layout_default(&swr.dst.ch_layout, dst_channel_count);
|
||||||
|
swr.dst.format = Audio_GetAVAudioFormat(AUDIO_WORKING_FORMAT);
|
||||||
|
swr_alloc_set_opts2(
|
||||||
|
&swr.ctx, &swr.dst.ch_layout, swr.dst.format, swr.dst.sample_rate,
|
||||||
|
&swr.src.ch_layout, swr.src.format, swr.src.sample_rate, 0, 0);
|
||||||
|
if (swr.ctx == nullptr) {
|
||||||
|
av_packet_unref(av.packet);
|
||||||
|
error_code = AVERROR(ENOMEM);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code = swr_init(swr.ctx);
|
||||||
|
if (error_code != 0) {
|
||||||
|
av_packet_unref(av.packet);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((error_code = av_read_frame(av.format_ctx, av.packet)) >= 0) {
|
||||||
|
M_DecodePacket(av.codec_ctx, av.packet, av.frame, &swr);
|
||||||
|
av_packet_unref(av.packet);
|
||||||
|
if (error_code < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (error_code < 0) {
|
if (av.codec_ctx != nullptr) {
|
||||||
av_packet_unref(av.packet);
|
M_DecodePacket(av.codec_ctx, nullptr, av.frame, &swr);
|
||||||
goto cleanup;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
error_code = avcodec_send_packet(av.codec_ctx, av.packet);
|
if (error_code == AVERROR_EOF) {
|
||||||
if (error_code < 0) {
|
error_code = 0;
|
||||||
av_packet_unref(av.packet);
|
} else if (error_code < 0) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
if (swr.ctx == nullptr) {
|
|
||||||
swr.src.sample_rate = av.codec_ctx->sample_rate;
|
|
||||||
swr.src.ch_layout = av.codec_ctx->ch_layout;
|
|
||||||
swr.src.format = av.codec_ctx->sample_fmt;
|
|
||||||
swr.dst.sample_rate = AUDIO_WORKING_RATE;
|
|
||||||
av_channel_layout_default(&swr.dst.ch_layout, dst_channel_count);
|
|
||||||
swr.dst.format = Audio_GetAVAudioFormat(AUDIO_WORKING_FORMAT);
|
|
||||||
swr_alloc_set_opts2(
|
|
||||||
&swr.ctx, &swr.dst.ch_layout, swr.dst.format,
|
|
||||||
swr.dst.sample_rate, &swr.src.ch_layout, swr.src.format,
|
|
||||||
swr.src.sample_rate, 0, 0);
|
|
||||||
if (swr.ctx == nullptr) {
|
|
||||||
av_packet_unref(av.packet);
|
|
||||||
error_code = AVERROR(ENOMEM);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_code = swr_init(swr.ctx);
|
|
||||||
if (error_code != 0) {
|
|
||||||
av_packet_unref(av.packet);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
error_code = avcodec_receive_frame(av.codec_ctx, av.frame);
|
|
||||||
if (error_code == AVERROR(EAGAIN)) {
|
|
||||||
av_frame_unref(av.frame);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error_code < 0) {
|
|
||||||
av_packet_unref(av.packet);
|
|
||||||
av_frame_unref(av.frame);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *out_buffer = nullptr;
|
|
||||||
const int32_t out_samples =
|
|
||||||
swr_get_out_samples(swr.ctx, av.frame->nb_samples);
|
|
||||||
av_samples_alloc(
|
|
||||||
&out_buffer, nullptr, swr.dst.ch_layout.nb_channels,
|
|
||||||
out_samples, swr.dst.format, 1);
|
|
||||||
int32_t resampled_size = swr_convert(
|
|
||||||
swr.ctx, &out_buffer, out_samples,
|
|
||||||
(const uint8_t **)av.frame->data, av.frame->nb_samples);
|
|
||||||
while (resampled_size > 0) {
|
|
||||||
int32_t out_buffer_size = av_samples_get_buffer_size(
|
|
||||||
nullptr, swr.dst.ch_layout.nb_channels, resampled_size,
|
|
||||||
swr.dst.format, 1);
|
|
||||||
|
|
||||||
if (out_buffer_size > 0) {
|
|
||||||
working_buffer = Memory_Realloc(
|
|
||||||
working_buffer, working_buffer_size + out_buffer_size);
|
|
||||||
if (out_buffer) {
|
|
||||||
memcpy(
|
|
||||||
(uint8_t *)working_buffer + working_buffer_size,
|
|
||||||
out_buffer, out_buffer_size);
|
|
||||||
}
|
|
||||||
working_buffer_size += out_buffer_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
resampled_size =
|
|
||||||
swr_convert(swr.ctx, &out_buffer, out_samples, nullptr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
av_freep(&out_buffer);
|
|
||||||
av_frame_unref(av.frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
av_packet_unref(av.packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_size != nullptr) {
|
if (out_size != nullptr) {
|
||||||
*out_size = working_buffer_size;
|
*out_size = swr.working_buffer_size;
|
||||||
}
|
}
|
||||||
if (out_sample_count != nullptr) {
|
if (out_sample_count != nullptr) {
|
||||||
*out_sample_count = (int32_t)(working_buffer_size
|
*out_sample_count = (int32_t)swr.working_buffer_size
|
||||||
/ av_get_bytes_per_sample(swr.dst.format))
|
/ av_get_bytes_per_sample(swr.dst.format)
|
||||||
/ swr.dst.ch_layout.nb_channels;
|
/ swr.dst.ch_layout.nb_channels;
|
||||||
}
|
}
|
||||||
if (out_sample_data != nullptr) {
|
if (out_sample_data != nullptr) {
|
||||||
*out_sample_data = (uint8_t *)working_buffer;
|
*out_sample_data = swr.working_buffer;
|
||||||
} else {
|
} else {
|
||||||
Memory_FreePointer(&working_buffer);
|
Memory_FreePointer(&swr.working_buffer);
|
||||||
}
|
}
|
||||||
result = true;
|
result = true;
|
||||||
|
|
||||||
|
@ -366,20 +382,6 @@ cleanup:
|
||||||
LOG_ERROR("Error while decoding sample: %s", av_err2str(error_code));
|
LOG_ERROR("Error while decoding sample: %s", av_err2str(error_code));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (swr.ctx) {
|
|
||||||
swr_free(&swr.ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (av.frame) {
|
|
||||||
av_frame_free(&av.frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (av.packet) {
|
|
||||||
av_packet_free(&av.packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
av.codec = nullptr;
|
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
if (out_size != nullptr) {
|
if (out_size != nullptr) {
|
||||||
*out_size = 0;
|
*out_size = 0;
|
||||||
|
@ -390,22 +392,29 @@ cleanup:
|
||||||
if (out_sample_data != nullptr) {
|
if (out_sample_data != nullptr) {
|
||||||
*out_sample_data = nullptr;
|
*out_sample_data = nullptr;
|
||||||
}
|
}
|
||||||
Memory_FreePointer(&working_buffer);
|
Memory_FreePointer(&swr.working_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (swr.ctx) {
|
||||||
|
swr_free(&swr.ctx);
|
||||||
|
}
|
||||||
|
if (av.frame) {
|
||||||
|
av_frame_free(&av.frame);
|
||||||
|
}
|
||||||
|
if (av.packet) {
|
||||||
|
av_packet_free(&av.packet);
|
||||||
|
}
|
||||||
|
av.codec = nullptr;
|
||||||
if (av.codec_ctx) {
|
if (av.codec_ctx) {
|
||||||
avcodec_free_context(&av.codec_ctx);
|
avcodec_free_context(&av.codec_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (av.format_ctx) {
|
if (av.format_ctx) {
|
||||||
avformat_close_input(&av.format_ctx);
|
avformat_close_input(&av.format_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (av.avio_context) {
|
if (av.avio_context) {
|
||||||
av_freep(&av.avio_context->buffer);
|
av_freep(&av.avio_context->buffer);
|
||||||
avio_context_free(&av.avio_context);
|
avio_context_free(&av.avio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue