|
|
@ -7,19 +7,19 @@ |
|
|
|
* qoaplay also provides some functions to seek to a specific frame. |
|
|
|
* |
|
|
|
* LICENSE: MIT License |
|
|
|
* |
|
|
|
* |
|
|
|
* Copyright (c) 2023 Dominic Szablewski (@phoboslab), reviewed by Ramon Santamaria (@raysan5) |
|
|
|
* |
|
|
|
* |
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
|
|
* of this software and associated documentation files (the "Software"), to deal |
|
|
|
* in the Software without restriction, including without limitation the rights |
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
|
|
* copies of the Software, and to permit persons to whom the Software is |
|
|
|
* furnished to do so, subject to the following conditions: |
|
|
|
* |
|
|
|
* |
|
|
|
* The above copyright notice and this permission notice shall be included in all |
|
|
|
* copies or substantial portions of the Software. |
|
|
|
* |
|
|
|
* |
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
|
@ -121,7 +121,7 @@ qoaplay_desc *qoaplay_open(char *path) |
|
|
|
qoa_ctx->info.channels = qoa.channels; |
|
|
|
qoa_ctx->info.samplerate = qoa.samplerate; |
|
|
|
qoa_ctx->info.samples = qoa.samples; |
|
|
|
|
|
|
|
|
|
|
|
return qoa_ctx; |
|
|
|
} |
|
|
|
|
|
|
@ -174,15 +174,15 @@ void qoaplay_close(qoaplay_desc *qoa_ctx) |
|
|
|
QOA_FREE(qoa_ctx->file_data); |
|
|
|
qoa_ctx->file_data_size = 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
QOA_FREE(qoa_ctx); |
|
|
|
} |
|
|
|
|
|
|
|
// Decode one frame from QOA data |
|
|
|
unsigned int qoaplay_decode_frame(qoaplay_desc *qoa_ctx) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (qoa_ctx->file) qoa_ctx->buffer_len = fread(qoa_ctx->buffer, 1, qoa_max_frame_size(&qoa_ctx->info), qoa_ctx->file); |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
qoa_ctx->buffer_len = qoa_max_frame_size(&qoa_ctx->info); |
|
|
|
memcpy(qoa_ctx->buffer, qoa_ctx->file_data + qoa_ctx->file_data_offset, qoa_ctx->buffer_len); |
|
|
@ -193,14 +193,14 @@ unsigned int qoaplay_decode_frame(qoaplay_desc *qoa_ctx) |
|
|
|
qoa_decode_frame(qoa_ctx->buffer, qoa_ctx->buffer_len, &qoa_ctx->info, qoa_ctx->sample_data, &frame_len); |
|
|
|
qoa_ctx->sample_data_pos = 0; |
|
|
|
qoa_ctx->sample_data_len = frame_len; |
|
|
|
|
|
|
|
|
|
|
|
return frame_len; |
|
|
|
} |
|
|
|
|
|
|
|
// Rewind QOA file or memory pointer to beginning |
|
|
|
void qoaplay_rewind(qoaplay_desc *qoa_ctx) |
|
|
|
{ |
|
|
|
if (qoa_ctx->file) fseek(qoa_ctx->file, qoa_ctx->first_frame_pos, SEEK_SET); |
|
|
|
if (qoa_ctx->file) fseek(qoa_ctx->file, qoa_ctx->first_frame_pos, SEEK_SET); |
|
|
|
else qoa_ctx->file_data_offset = 0; |
|
|
|
|
|
|
|
qoa_ctx->sample_position = 0; |
|
|
@ -213,7 +213,7 @@ unsigned int qoaplay_decode(qoaplay_desc *qoa_ctx, float *sample_data, int num_s |
|
|
|
{ |
|
|
|
int src_index = qoa_ctx->sample_data_pos*qoa_ctx->info.channels; |
|
|
|
int dst_index = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < num_samples; i++) |
|
|
|
{ |
|
|
|
// Do we have to decode more samples? |
|
|
@ -225,20 +225,20 @@ unsigned int qoaplay_decode(qoaplay_desc *qoa_ctx, float *sample_data, int num_s |
|
|
|
qoaplay_rewind(qoa_ctx); |
|
|
|
qoaplay_decode_frame(qoa_ctx); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
src_index = 0; |
|
|
|
} |
|
|
|
|
|
|
|
// Normalize to -1..1 floats and write to dest |
|
|
|
for (int c = 0; c < qoa_ctx->info.channels; c++) |
|
|
|
for (int c = 0; c < qoa_ctx->info.channels; c++) |
|
|
|
{ |
|
|
|
sample_data[dst_index++] = qoa_ctx->sample_data[src_index++]/32768.0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
qoa_ctx->sample_data_pos++; |
|
|
|
qoa_ctx->sample_position++; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return num_samples; |
|
|
|
} |
|
|
|
|
|
|
@ -272,7 +272,7 @@ void qoaplay_seek_frame(qoaplay_desc *qoa_ctx, int frame) |
|
|
|
qoa_ctx->sample_data_pos = 0; |
|
|
|
|
|
|
|
unsigned int offset = qoa_ctx->first_frame_pos + frame*qoa_max_frame_size(&qoa_ctx->info); |
|
|
|
|
|
|
|
|
|
|
|
if (qoa_ctx->file) fseek(qoa_ctx->file, offset, SEEK_SET); |
|
|
|
else qoa_ctx->file_data_offset = offset; |
|
|
|
} |