mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Add support for initializing an encoder from a VFS.
This commit is contained in:
+90
-57
@@ -9371,8 +9371,8 @@ Encoders do not perform any format conversion for you. If your target format doe
|
|||||||
#ifndef MA_NO_ENCODING
|
#ifndef MA_NO_ENCODING
|
||||||
typedef struct ma_encoder ma_encoder;
|
typedef struct ma_encoder ma_encoder;
|
||||||
|
|
||||||
typedef size_t (* ma_encoder_write_proc) (ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite); /* Returns the number of bytes written. */
|
typedef ma_result (* ma_encoder_write_proc) (ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite, size_t* pBytesWritten);
|
||||||
typedef ma_bool32 (* ma_encoder_seek_proc) (ma_encoder* pEncoder, int byteOffset, ma_seek_origin origin);
|
typedef ma_result (* ma_encoder_seek_proc) (ma_encoder* pEncoder, ma_int64 offset, ma_seek_origin origin);
|
||||||
typedef ma_result (* ma_encoder_init_proc) (ma_encoder* pEncoder);
|
typedef ma_result (* ma_encoder_init_proc) (ma_encoder* pEncoder);
|
||||||
typedef void (* ma_encoder_uninit_proc) (ma_encoder* pEncoder);
|
typedef void (* ma_encoder_uninit_proc) (ma_encoder* pEncoder);
|
||||||
typedef ma_result (* ma_encoder_write_pcm_frames_proc)(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount, ma_uint64* pFramesWritten);
|
typedef ma_result (* ma_encoder_write_pcm_frames_proc)(ma_encoder* pEncoder, const void* pFramesIn, ma_uint64 frameCount, ma_uint64* pFramesWritten);
|
||||||
@@ -9398,10 +9398,19 @@ struct ma_encoder
|
|||||||
ma_encoder_write_pcm_frames_proc onWritePCMFrames;
|
ma_encoder_write_pcm_frames_proc onWritePCMFrames;
|
||||||
void* pUserData;
|
void* pUserData;
|
||||||
void* pInternalEncoder; /* <-- The drwav/drflac/stb_vorbis/etc. objects. */
|
void* pInternalEncoder; /* <-- The drwav/drflac/stb_vorbis/etc. objects. */
|
||||||
void* pFile; /* FILE*. Only used when initialized with ma_encoder_init_file(). */
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
ma_vfs* pVFS;
|
||||||
|
ma_vfs_file file;
|
||||||
|
} vfs;
|
||||||
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
MA_API ma_result ma_encoder_init(ma_encoder_write_proc onWrite, ma_encoder_seek_proc onSeek, void* pUserData, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
|
MA_API ma_result ma_encoder_init(ma_encoder_write_proc onWrite, ma_encoder_seek_proc onSeek, void* pUserData, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
|
||||||
|
MA_API ma_result ma_encoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
|
||||||
|
MA_API ma_result ma_encoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
|
||||||
MA_API ma_result ma_encoder_init_file(const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
|
MA_API ma_result ma_encoder_init_file(const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
|
||||||
MA_API ma_result ma_encoder_init_file_w(const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
|
MA_API ma_result ma_encoder_init_file_w(const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder);
|
||||||
MA_API void ma_encoder_uninit(ma_encoder* pEncoder);
|
MA_API void ma_encoder_uninit(ma_encoder* pEncoder);
|
||||||
@@ -61444,17 +61453,27 @@ MA_API ma_result ma_decode_memory(const void* pData, size_t dataSize, ma_decoder
|
|||||||
static size_t ma_encoder__internal_on_write_wav(void* pUserData, const void* pData, size_t bytesToWrite)
|
static size_t ma_encoder__internal_on_write_wav(void* pUserData, const void* pData, size_t bytesToWrite)
|
||||||
{
|
{
|
||||||
ma_encoder* pEncoder = (ma_encoder*)pUserData;
|
ma_encoder* pEncoder = (ma_encoder*)pUserData;
|
||||||
|
size_t bytesWritten = 0;
|
||||||
|
|
||||||
MA_ASSERT(pEncoder != NULL);
|
MA_ASSERT(pEncoder != NULL);
|
||||||
|
|
||||||
return pEncoder->onWrite(pEncoder, pData, bytesToWrite);
|
pEncoder->onWrite(pEncoder, pData, bytesToWrite, &bytesWritten);
|
||||||
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
static drwav_bool32 ma_encoder__internal_on_seek_wav(void* pUserData, int offset, drwav_seek_origin origin)
|
static drwav_bool32 ma_encoder__internal_on_seek_wav(void* pUserData, int offset, drwav_seek_origin origin)
|
||||||
{
|
{
|
||||||
ma_encoder* pEncoder = (ma_encoder*)pUserData;
|
ma_encoder* pEncoder = (ma_encoder*)pUserData;
|
||||||
|
ma_result result;
|
||||||
|
|
||||||
MA_ASSERT(pEncoder != NULL);
|
MA_ASSERT(pEncoder != NULL);
|
||||||
|
|
||||||
return pEncoder->onSeek(pEncoder, offset, (origin == drwav_seek_origin_start) ? ma_seek_origin_start : ma_seek_origin_current);
|
result = pEncoder->onSeek(pEncoder, offset, (origin == drwav_seek_origin_start) ? ma_seek_origin_start : ma_seek_origin_current);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return DRWAV_FALSE;
|
||||||
|
} else {
|
||||||
|
return DRWAV_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ma_result ma_encoder__on_init_wav(ma_encoder* pEncoder)
|
static ma_result ma_encoder__on_init_wav(ma_encoder* pEncoder)
|
||||||
@@ -61610,68 +61629,80 @@ MA_API ma_result ma_encoder_init__internal(ma_encoder_write_proc onWrite, ma_enc
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API size_t ma_encoder__on_write_stdio(ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite)
|
static ma_result ma_encoder__on_write_vfs(ma_encoder* pEncoder, const void* pBufferIn, size_t bytesToWrite, size_t* pBytesWritten)
|
||||||
{
|
{
|
||||||
return fwrite(pBufferIn, 1, bytesToWrite, (FILE*)pEncoder->pFile);
|
return ma_vfs_or_default_write(pEncoder->data.vfs.pVFS, pEncoder->data.vfs.file, pBufferIn, bytesToWrite, pBytesWritten);
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_bool32 ma_encoder__on_seek_stdio(ma_encoder* pEncoder, int byteOffset, ma_seek_origin origin)
|
static ma_result ma_encoder__on_seek_vfs(ma_encoder* pEncoder, ma_int64 offset, ma_seek_origin origin)
|
||||||
{
|
{
|
||||||
return fseek((FILE*)pEncoder->pFile, byteOffset, (origin == ma_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
|
return ma_vfs_or_default_seek(pEncoder->data.vfs.pVFS, pEncoder->data.vfs.file, offset, origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_encoder_init_vfs(ma_vfs* pVFS, const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
|
||||||
|
{
|
||||||
|
ma_result result;
|
||||||
|
ma_vfs_file file;
|
||||||
|
|
||||||
|
result = ma_encoder_preinit(pConfig, pEncoder);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now open the file. If this fails we don't need to uninitialize the encoder. */
|
||||||
|
result = ma_vfs_or_default_open(pVFS, pFilePath, MA_OPEN_MODE_WRITE, &file);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pEncoder->data.vfs.pVFS = pVFS;
|
||||||
|
pEncoder->data.vfs.file = file;
|
||||||
|
|
||||||
|
result = ma_encoder_init__internal(ma_encoder__on_write_vfs, ma_encoder__on_seek_vfs, NULL, pEncoder);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
ma_vfs_or_default_close(pVFS, file);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_encoder_init_vfs_w(ma_vfs* pVFS, const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
|
||||||
|
{
|
||||||
|
ma_result result;
|
||||||
|
ma_vfs_file file;
|
||||||
|
|
||||||
|
result = ma_encoder_preinit(pConfig, pEncoder);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now open the file. If this fails we don't need to uninitialize the encoder. */
|
||||||
|
result = ma_vfs_or_default_open_w(pVFS, pFilePath, MA_OPEN_MODE_WRITE, &file);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pEncoder->data.vfs.pVFS = pVFS;
|
||||||
|
pEncoder->data.vfs.file = file;
|
||||||
|
|
||||||
|
result = ma_encoder_init__internal(ma_encoder__on_write_vfs, ma_encoder__on_seek_vfs, NULL, pEncoder);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
ma_vfs_or_default_close(pVFS, file);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_encoder_init_file(const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
|
MA_API ma_result ma_encoder_init_file(const char* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
|
||||||
{
|
{
|
||||||
ma_result result;
|
return ma_encoder_init_vfs(NULL, pFilePath, pConfig, pEncoder);
|
||||||
FILE* pFile;
|
|
||||||
|
|
||||||
result = ma_encoder_preinit(pConfig, pEncoder);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now open the file. If this fails we don't need to uninitialize the encoder. */
|
|
||||||
result = ma_fopen(&pFile, pFilePath, "wb");
|
|
||||||
if (pFile == NULL) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pEncoder->pFile = pFile;
|
|
||||||
|
|
||||||
result = ma_encoder_init__internal(ma_encoder__on_write_stdio, ma_encoder__on_seek_stdio, NULL, pEncoder);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
fclose(pFile);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_encoder_init_file_w(const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
|
MA_API ma_result ma_encoder_init_file_w(const wchar_t* pFilePath, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
|
||||||
{
|
{
|
||||||
ma_result result;
|
return ma_encoder_init_vfs_w(NULL, pFilePath, pConfig, pEncoder);
|
||||||
FILE* pFile;
|
|
||||||
|
|
||||||
result = ma_encoder_preinit(pConfig, pEncoder);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now open the file. If this fails we don't need to uninitialize the encoder. */
|
|
||||||
result = ma_wfopen(&pFile, pFilePath, L"wb", &pEncoder->config.allocationCallbacks);
|
|
||||||
if (pFile == NULL) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pEncoder->pFile = pFile;
|
|
||||||
|
|
||||||
result = ma_encoder_init__internal(ma_encoder__on_write_stdio, ma_encoder__on_seek_stdio, NULL, pEncoder);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
fclose(pFile);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MA_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_encoder_init(ma_encoder_write_proc onWrite, ma_encoder_seek_proc onSeek, void* pUserData, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
|
MA_API ma_result ma_encoder_init(ma_encoder_write_proc onWrite, ma_encoder_seek_proc onSeek, void* pUserData, const ma_encoder_config* pConfig, ma_encoder* pEncoder)
|
||||||
@@ -61698,8 +61729,9 @@ MA_API void ma_encoder_uninit(ma_encoder* pEncoder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If we have a file handle, close it. */
|
/* If we have a file handle, close it. */
|
||||||
if (pEncoder->onWrite == ma_encoder__on_write_stdio) {
|
if (pEncoder->onWrite == ma_encoder__on_write_vfs) {
|
||||||
fclose((FILE*)pEncoder->pFile);
|
ma_vfs_or_default_close(pEncoder->data.vfs.pVFS, pEncoder->data.vfs.file);
|
||||||
|
pEncoder->data.vfs.file = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89548,6 +89580,7 @@ There have also been some other smaller changes added to this release.
|
|||||||
REVISION HISTORY
|
REVISION HISTORY
|
||||||
================
|
================
|
||||||
v0.11.4 - TBD
|
v0.11.4 - TBD
|
||||||
|
- Add support for initializing an encoder from a VFS.
|
||||||
- Fix a bug when initializing an encoder from a file where the file handle does not get closed in
|
- Fix a bug when initializing an encoder from a file where the file handle does not get closed in
|
||||||
the event of an error.
|
the event of an error.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user