将文件中的音频与生成的声音混合
Mixing audio from files with generated sound
我正在使用此处找到的示例:https://developer.xamarin.com/samples/monotouch/MultichannelMixer/
我修改了示例,将第三个输入添加到混频器,这是一个简单的正弦波。我想让这两个音频文件与正弦波一起播放。为此,我为正弦波指定一个单独的 AudioStreamBasicDescription
,并在混频器的 HandleRenderDelegate
内编写代码以生成其样本。
我面临的问题是,只有当我使用带有浮点样本的音频格式而不是正弦波的带符号整数时,这才有效。如果我尝试使用整数,结果是音频文件的声音严重失真并且没有正弦波。
这是我用于浮点格式的代码(有效)
desc = new AudioStreamBasicDescription()
{
BitsPerChannel = 32,
Format = AudioFormatType.LinearPCM,
FormatFlags = AudioFormatFlags.IsFloat | AudioFormatFlags.IsPacked,
SampleRate = 44100,
ChannelsPerFrame = 1,
FramesPerPacket = 1,
BytesPerFrame = 2,
BytesPerPacket = 2
};
在HandleRenderDelegate
中生成正弦波
if (busNumber == 2) { // generate sine wave
var outL = (float*)data[0].Data;
var outR = (float*)data[1].Data;
float s;
for (int i = 0; i < numberFrames; i++) {
s = (float)(Math.Sin((double)pitchSample / (44100 / 440) * 2 * Math.PI)) * .2f;
pitchSample++;
outL[i] = outR[i] = s;
}
return AudioUnitStatus.OK;
}
上面的代码按预期工作,但现在我想对正弦波使用有符号整数格式。所以我修改格式:
desc = new AudioStreamBasicDescription()
{
BitsPerChannel = 32,
Format = AudioFormatType.LinearPCM,
FormatFlags = AudioFormatFlags.IsSignedInteger | AudioFormatFlags.IsPacked,
SampleRate = 44100,
ChannelsPerFrame = 1,
FramesPerPacket = 1,
BytesPerFrame = 2,
BytesPerPacket = 2
};
波发生器:
if (busNumber == 2) {
var outL = (int*)data[0].Data;
var outR = (int*)data[1].Data;
short s;
for (int i = 0; i < numberFrames; i++) {
s = (short)(Math.Sin((double)pitchSample / (44100 / 440) * 2 * Math.PI) * .2 * Int16.MaxValue);
pitchSample++;
outL[i] = outR[i] = s;
}
return AudioUnitStatus.OK;
}
使用修改后的代码,我得到了失真的音频文件,没有正弦波。
为什么它适用于浮点样本而不适用于整数?
我不确定这些是唯一的问题,但您的设置不一致:
- BitsPerChannel 设置为 32 而不是 16
- 你想转换为
(short *)
而不是 (int *)
- ChannelsPerFrame 设置为 1,但你在生成器中设置了立体声(我不确定这是不是一个错误)
(我在这里假设你想使用 16 位有符号整数。)
注意:在 float 情况下 BytesPerFrame
和 BytesPerPacked
应该是 4
我正在使用此处找到的示例:https://developer.xamarin.com/samples/monotouch/MultichannelMixer/
我修改了示例,将第三个输入添加到混频器,这是一个简单的正弦波。我想让这两个音频文件与正弦波一起播放。为此,我为正弦波指定一个单独的 AudioStreamBasicDescription
,并在混频器的 HandleRenderDelegate
内编写代码以生成其样本。
我面临的问题是,只有当我使用带有浮点样本的音频格式而不是正弦波的带符号整数时,这才有效。如果我尝试使用整数,结果是音频文件的声音严重失真并且没有正弦波。
这是我用于浮点格式的代码(有效)
desc = new AudioStreamBasicDescription()
{
BitsPerChannel = 32,
Format = AudioFormatType.LinearPCM,
FormatFlags = AudioFormatFlags.IsFloat | AudioFormatFlags.IsPacked,
SampleRate = 44100,
ChannelsPerFrame = 1,
FramesPerPacket = 1,
BytesPerFrame = 2,
BytesPerPacket = 2
};
在HandleRenderDelegate
if (busNumber == 2) { // generate sine wave
var outL = (float*)data[0].Data;
var outR = (float*)data[1].Data;
float s;
for (int i = 0; i < numberFrames; i++) {
s = (float)(Math.Sin((double)pitchSample / (44100 / 440) * 2 * Math.PI)) * .2f;
pitchSample++;
outL[i] = outR[i] = s;
}
return AudioUnitStatus.OK;
}
上面的代码按预期工作,但现在我想对正弦波使用有符号整数格式。所以我修改格式:
desc = new AudioStreamBasicDescription()
{
BitsPerChannel = 32,
Format = AudioFormatType.LinearPCM,
FormatFlags = AudioFormatFlags.IsSignedInteger | AudioFormatFlags.IsPacked,
SampleRate = 44100,
ChannelsPerFrame = 1,
FramesPerPacket = 1,
BytesPerFrame = 2,
BytesPerPacket = 2
};
波发生器:
if (busNumber == 2) {
var outL = (int*)data[0].Data;
var outR = (int*)data[1].Data;
short s;
for (int i = 0; i < numberFrames; i++) {
s = (short)(Math.Sin((double)pitchSample / (44100 / 440) * 2 * Math.PI) * .2 * Int16.MaxValue);
pitchSample++;
outL[i] = outR[i] = s;
}
return AudioUnitStatus.OK;
}
使用修改后的代码,我得到了失真的音频文件,没有正弦波。
为什么它适用于浮点样本而不适用于整数?
我不确定这些是唯一的问题,但您的设置不一致:
- BitsPerChannel 设置为 32 而不是 16
- 你想转换为
(short *)
而不是(int *)
- ChannelsPerFrame 设置为 1,但你在生成器中设置了立体声(我不确定这是不是一个错误)
(我在这里假设你想使用 16 位有符号整数。)
注意:在 float 情况下 BytesPerFrame
和 BytesPerPacked
应该是 4