Iphone 如何将一个音频文件添加到另一个音频文件?

Iphone 如何将一个音频文件添加到另一个音频文件?,iphone,ios,audio,merge,record,Iphone,Ios,Audio,Merge,Record,我有一个音乐音频文件,我需要录制歌曲的小片段,并在不同的时间添加到音乐文件中。你可以这样理解,我有一张长纸条,我必须把小纸条贴在大纸条的不同位置。 请提出一些建议 让我在这里提供更多细节。假设我有10个5秒的小声音片段,我有一个50秒的音乐文件。所以我总共有11个声音文件。现在我必须创建一个最终的音频文件,在音乐文件上添加不同时间后的10个小片段。第一个文件应在5.22秒时添加,第二个文件应在10.34秒时添加 我将根据您在评论中的澄清回答: 假设我有两个mp3文件,a.mp3为5秒,b.mp3

我有一个音乐音频文件,我需要录制歌曲的小片段,并在不同的时间添加到音乐文件中。你可以这样理解,我有一张长纸条,我必须把小纸条贴在大纸条的不同位置。 请提出一些建议


让我在这里提供更多细节。假设我有10个5秒的小声音片段,我有一个50秒的音乐文件。所以我总共有11个声音文件。现在我必须创建一个最终的音频文件,在音乐文件上添加不同时间后的10个小片段。第一个文件应在5.22秒时添加,第二个文件应在10.34秒时添加

我将根据您在评论中的澄清回答:

假设我有两个mp3文件,a.mp3为5秒,b.mp3为7秒 秒,我想混合它们,以生成c.mp3的持续时间 7秒

如评论中所述,我无法向您提供任何iOS细节,但我可以让您了解执行此过程在逻辑上需要什么,而不管使用什么平台和库。我将使用简单的C++代码段来演示。然而,听起来你想做的是将a.mp3(以下简称a)混合到b.mp3(以下简称b)的某个地方——让我们说将a混合到b的开头——以生成最终的音频片段C

最重要的是,由于您提到它们是MP3文件,而不是WAV或其他未压缩的PCM格式,如RAW或AIFF,因此首先需要将A和B转换为未压缩的格式,如
S16_LE
PCM(CD音频格式——带符号的16位整数采样,小尾端),这意味着您将使用一个样本值数组——如果立体声音频,左声道和右声道交错——用于A和B,因此C,最后一个可能在您完成混音后被选择性地重新编码为MP3

您应该使用库来处理文件编码/格式问题,但在使用它们时,它们(包括用于直接录制或回放的系统接口)都会产生(即读取时)或期望(即写入时)基本相同的基本未压缩PCM样本流格式。对于一般开发,除了您可能应该关注的WAV格式变体之外,无处不在的
libsndfile
C库对于处理47种文件格式(包括Ogg Vorbis和FLAC)(但不支持直接的MP3)的所有这些非常有用

为简单起见,我们只考虑单声道声音片段A和B(即,A和B的样本值是直的数组,我们不必担心交错的左/右通道);如果有必要,您可以通过独立地考虑每个立体声通道(A.左混音与B.左混音,A.右混音与B.右混音),轻松地将概念扩展到立体声。如果您特定的A和B是立体声,但C不需要,您也可以根据应用程序,将两个输入音频剪辑预先转换为单声道

此外,将音频样本作为浮点值使用通常更容易,因此将未压缩样本格式转换为[-1.0,+1.0]范围内的浮点值(或者通常由音频文件库为您执行--
libsndfile
does),其中,绝对值1.0表示最大可能的采样值,0.0表示静音。这些采样值包括任意音频波形随时间(即,在阵列上)的演变

首先,在混音之前,您需要确保您有足够的“净空”(防止输出中的剪辑)。为什么?混合使用信号叠加(加法)的原理来组合信号/声音:我们将为每个重叠样本加上A和B,因此,如果A和B的相应样本之和超过1.0或低于-1.0,则混合输出样本可能会“剪裁”

有几种方法可以防止剪切,具体取决于您各自的输入电平,以及您是希望保留它们的音量比还是简单地将它们平均组合(或者您是否正在使用立体声,并希望使用A或B中声音最大的通道作为参考点,这是我们最后听到的立体声)

我们将采用最简单的方法,对A和B的体积进行归一化,使其在不超过满量程一半(0.5)的情况下达到峰值,这样当它们加在一起时,它们将永远不会剪裁(即,任何混合输出样本都不会超过范围[-1.0,+1.0])。如果用这种方法同时混合3个输入音频片段X、Y和Z,而不是2个输入,我们会在峰值(0.33)处将每个音频片段标准化为满标度的1/3

通过迭代A和B各自的样本缓冲区/数组并确定每个缓冲区/数组中的最大样本值,找到A和B的峰值,
A_peak
B_peak
。[要遵循的代码。]

A_scale * A_peak == 0.5
B_scale * B_peak == 0.5
分别为每个样本缓冲区a和B确定缩放值
a_scale
B_scale
,使其与各自峰值相乘产生半个刻度。[要遵循的代码。]

A_scale * A_peak == 0.5
B_scale * B_peak == 0.5
因此:

现在,我们可以将整个样本缓冲区A和B分别乘以
A_标度
B_标度
,它们将在精确的半标度处标准化为峰值,并且这两个样本的混合样本不会超过满标度。也就是说,即使样本的A和B的最大值对齐,它们的缩放和求和混合输出也将精确为1.0,并且永远不会更大。这种比例系数通常被称为“增益”

同样,在混音时,有多种方法规范化两个或多个采样缓冲区(音频剪辑)之间的增益,但这是演示中最简单和最通用的方法。此外,它还可以轻松地将N个不同的音频片段混合在一起(如上所述),并稍微简化,实时混合样本流(其中整个aud
unsigned int C_len = max(A_len, B_len);
double C[] = new double[ C_len ];
double A_peak = -1.0, B_peak = -1.0;

for (unsigned int i = 0; i < A_len; ++i) A_peak = max( A_peak, fabs(A[i]) );
for (unsigned int i = 0; i < B_len; ++i) B_peak = max( B_peak, fabs(B[i]) );
double A_scale = 1 / ( 2 * A_peak );
double B_scale = 1 / ( 2 * B_peak );
assert(A_len <= B_len);
assert(B_len == C_len);

unsigned int x = 0;

for (; x < A_len; ++x)
  C[x] = A_scale * A[x] + B_scale * B[x]; // actual mixing of A and B, finally

for (; x < B_len; ++x)
  C[x] = B_scale * B[x]; // as if A[x] were zero & no abrupt gain change