簡體   English   中英

如何使用ov_open_callbacks從流中打開Ogg Vorbis文件

[英]How to use ov_open_callbacks to open an Ogg Vorbis file from a stream

打開Ogg Vorbis文件的標准方法是使用ov_fopenov_open 但是,如果文件路徑包含非ASCII字符,則這兩個功能在Windows上均不起作用。

在這種情況下,可以包裝現有的std::ifstream (或其他輸入流)並通過ov_open_callbacks打開它。 當我嘗試執行此操作時,我發現文檔對所需包裝函數的確切語義有些粗略。

如何包裝現有流以便將其傳遞給ov_open_callbacks

這是一個工作示例,該示例打開一個.ogg文件並輸出一些基本信息。 所有包裝函數(在這種情況下不需要close除外)都已實現,因此生成的OggVorbis_File結構是完全可搜索的。

#include <vorbis/vorbisfile.h>
#include <iostream>
#include <cassert>
#include <fstream>
#include <iomanip>
#include <vector>

size_t read(void* buffer, size_t elementSize, size_t elementCount, void* dataSource) {
    assert(elementSize == 1);

    std::ifstream& stream = *static_cast<std::ifstream*>(dataSource);
    stream.read(static_cast<char*>(buffer), elementCount);
    const std::streamsize bytesRead = stream.gcount();
    stream.clear(); // In case we read past EOF
    return static_cast<size_t>(bytesRead);
}

int seek(void* dataSource, ogg_int64_t offset, int origin) {
    static const std::vector<std::ios_base::seekdir> seekDirections{
        std::ios_base::beg, std::ios_base::cur, std::ios_base::end
    };

    std::ifstream& stream = *static_cast<std::ifstream*>(dataSource);
    stream.seekg(offset, seekDirections.at(origin));
    stream.clear(); // In case we seeked to EOF
    return 0;
}

long tell(void* dataSource) {
    std::ifstream& stream = *static_cast<std::ifstream*>(dataSource);
    const auto position = stream.tellg();
    assert(position >= 0);
    return static_cast<long>(position);
}

int main() {
    // Open file stream
    std::ifstream stream;
    stream.open("C:\\path\\to\\file.ogg", std::ios::binary);
    OggVorbis_File file;
    const ov_callbacks callbacks{read, seek, nullptr, tell};
    int result = ov_open_callbacks(&stream, &file, nullptr, 0, callbacks);
    if (result < 0) {
        std::cout << "Error opening file: " << result << std::endl;
        return 0;
    }

    // Read file info
    vorbis_info* vorbisInfo = ov_info(&file, -1);
    std::cout << "File info: " << vorbisInfo->rate << "Hz, "
        << vorbisInfo->channels << " channels" << std::endl;

    // Close file
    ov_clear(&file);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM