如何使用ov_open_callbacks从流中打开Ogg Vorbis文件

丹尼尔·沃尔夫

打开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);
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Python中使用“ with open”打开多个文件?

如何使用open with语句打开文件

grails应用程序中的“打开的文件太多”-如何正确关闭打开的文件和流?

如何通过Spark打开/流.zip文件?

如何修复`无法打开流:PHP中打开文件太多错误'

Delphi使用流打开文件

如何在open()中使用相对路径在python中打开文件?

当我打开多个文件时,如何在Workbook_Open事件中关闭Excel文件?

分割Ogg Opus文件流

使用syscall open()在FUSE中打开文件

如何使用Java Sound缓冲和播放OGG文件中的声音数据

如何使用终端命令从文件夹中打开文件

用于编写flac,ogg vorbis和mp3 id3v2元数据的命令行工具?

在文件流中打开简单函数C ++

在iOS中实施Ogg Vorbis时出现文件未找到问题

使用元数据将Ogg Vorbis转换为MP3

将mp3转换为ogg vorbis

如何使用ffmpeg将Vorbis音频和VP8视频混合为WebM格式?

如何使用ffmpeg编码ogg音频文件?

通过DLNA将FLAC,Ogg Vorbis和Opus文件播放到渲染器

使用Ogg Flac和Vorbis在Fedora中构建libsndfile

如何确定Vorbis流的长度(以秒为单位)?

如何制作vorbis-tools ogg123的静态二进制构建?

如何使用IGraphBuilder播放Ogg Vorbis文件

您如何打开文件流以使用Scrapy进行阅读?

将TargetDataLine数据编码为Ogg Vorbis文件

如何通过 Ogg Vorbis 字节缓冲区获得采样率

如何使用内存流而不是文件流

如何使用 C 在 iOS 中打开文件?