gpt4 book ai didi

IOS Core Audio - MP3 到 WAV 仅在 1 声道时工作,如何获得立体声?

转载 作者:行者123 更新时间:2023-12-01 19:32:07 26 4
gpt4 key购买 nike

目前正在接收一个输出 WAV 的 MP3 文件。我的代码在一段时间内运行良好,但我现在想更改它,导出的 WAV 是 2 声道立体声文件。

问题出在某个地方。这描述了所需的输出格式。

下面的代码是事先运行良好的(单声道):

AudioStreamBasicDescription outputFormat = new AudioStreamBasicDescription();
outputFormat.setFormat(AudioFormat.LinearPCM);
outputFormat.setFormatFlags(AudioFormatFlags.Canonical);
outputFormat.setBitsPerChannel(16);
outputFormat.setChannelsPerFrame(1);
outputFormat.setFramesPerPacket(1);
outputFormat.setBytesPerFrame(2);
outputFormat.setBytesPerPacket(2);
outputFormat.setSampleRate(pitch);

将其更改为 setChannelsPerFrame(2);没用。不知道还有什么需要改变的?

错误是:
Launcher[318:12909] 224: SetDataFormat failed
Launcher[318:12909] 367: EXCEPTION (1718449215): "create audio file"

org.robovm.apple.corefoundation.OSStatusException: 1718449215
at org.robovm.apple.corefoundation.OSStatusException.throwIfNecessary(OSStatusException.java:53)
at org.robovm.apple.audiotoolbox.ExtAudioFile.create(ExtAudioFile.java:80)
at package.Launcher.mp3ToPCM(Launcher.java:1108)
...

有问题的线在哪里
outputFileExtAudio = ExtAudioFile.create(outputFileURL, AudioFileType.WAVE, outputFormat, null, AudioFileFlags.EraseFile);
但是问题一定出在我的 outputFormat 的 AudioStreamBasicDescription 上,因为这是唯一更改为“2 个 channel ”的东西,突然它不再起作用了。

(这是 Java 代码,利用 RoboVM 转换为 native IOS 代码。)

最佳答案

您还需要更新尺寸。

在 Core Audio 中,一个样本是一个单一的值,而一帧是所有 channel 的一个样本。对于 PCM 音频,单个帧也是单个数据包。

对于 16 位单声道音频,帧和样本是同义词,占用 2 个字节。对于 16 位立体声音频,一帧由两个样本(左和右)组成,每个样本占用 2 个字节,每个帧占用 4 个字节。
AudioStreamBasicDescription 的值所描述的格式是否交错略有不同。

一般可以想到非交错 PCM AudioStreamBasicDescription像这样:

asbd.mBytesPerFrame     = asbd.mBitsPerChannel / 8;

交错 像这样:
asbd.mBytesPerFrame     = (asbd.mBitsPerChannel / 8) * asbd.mChannelsPerFrame;

两个
asbd.mFramesPerPacket   = 1;
asbd.mBytesPerPacket = asbd.mBytesPerFrame;
AudioFormatFlags.Canonical已弃用,但我在这里假设它等同于交错打包的 native 字节序有符号整数。

因此,对于您的情况,交错的 16 位立体声是:
AudioStreamBasicDescription outputFormat = new AudioStreamBasicDescription();
outputFormat.setFormat(AudioFormat.LinearPCM);
outputFormat.setFormatFlags(AudioFormatFlags.Canonical);

outputFormat.setSampleRate(pitch);
outputFormat.setChannelsPerFrame(2);
outputFormat.setBitsPerChannel(16);

outputFormat.setBytesPerFrame(4);
outputFormat.setFramesPerPacket(1);
outputFormat.setBytesPerPacket(4);

下面是两个显示关系的辅助函数(在 C++ 中):
static AudioFormatFlags CalculateLPCMFlags(UInt32 validBitsPerChannel, UInt32 totalBitsPerChannel, bool isFloat, bool isBigEndian, bool isNonInterleaved)
{
return (isFloat ? kAudioFormatFlagIsFloat : kAudioFormatFlagIsSignedInteger) | (isBigEndian ? ((UInt32)kAudioFormatFlagIsBigEndian) : 0) | ((validBitsPerChannel == totalBitsPerChannel) ? kAudioFormatFlagIsPacked : kAudioFormatFlagIsAlignedHigh) | (isNonInterleaved ? ((UInt32)kAudioFormatFlagIsNonInterleaved) : 0);
}

static void FillOutASBDForLPCM(AudioStreamBasicDescription *asbd, Float64 sampleRate, UInt32 channelsPerFrame, UInt32 validBitsPerChannel, UInt32 totalBitsPerChannel, bool isFloat, bool isBigEndian, bool isNonInterleaved)
{
asbd->mFormatID = kAudioFormatLinearPCM;
asbd->mFormatFlags = CalculateLPCMFlags(validBitsPerChannel, totalBitsPerChannel, isFloat, isBigEndian, isNonInterleaved);

asbd->mSampleRate = sampleRate;
asbd->mChannelsPerFrame = channelsPerFrame;
asbd->mBitsPerChannel = validBitsPerChannel;

asbd->mBytesPerPacket = (isNonInterleaved ? 1 : channelsPerFrame) * (totalBitsPerChannel / 8);
asbd->mFramesPerPacket = 1;
asbd->mBytesPerFrame = (isNonInterleaved ? 1 : channelsPerFrame) * (totalBitsPerChannel / 8);
}

关于IOS Core Audio - MP3 到 WAV 仅在 1 声道时工作,如何获得立体声?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62054103/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com