好吧,我不能告诉你你做错了什么。但我可以告诉你如何做你想做的事。
首先创建一个General Helper Functions:
public static class General {
public static void CopyBytes(byte[] dst, int dstOffset, byte[] src) {
Buffer.BlockCopy(src, 0, dst, dstOffset, src.Length);
}
}
public static class BitHelper {
public static int Read(ref ulong x, int length) {
int r = (int)(x >> (64 - length));
x <<= length;
return r;
}
public static int Read(byte[] bytes, ref int offset, int length) {
int startByte = offset / 8;
int endByte = (offset + length - 1) / 8;
int skipBits = offset % 8;
ulong bits = 0;
for (int i = 0; i <= Math.Min(endByte - startByte, 7); i++) {
bits |= (ulong)bytes[startByte + i] << (56 - (i * 8));
}
if (skipBits != 0) Read(ref bits, skipBits);
offset += length;
return Read(ref bits, length);
}
public static void Write(ref ulong x, int length, int value) {
ulong mask = 0xFFFFFFFFFFFFFFFF >> (64 - length);
x = (x << length) | ((ulong)value & mask);
}
public static byte[] CopyBlock(byte[] bytes, int offset, int length) {
int startByte = offset / 8;
int endByte = (offset + length - 1) / 8;
int shiftA = offset % 8;
int shiftB = 8 - shiftA;
byte[] dst = new byte[(length + 7) / 8];
if (shiftA == 0) {
Buffer.BlockCopy(bytes, startByte, dst, 0, dst.Length);
}
else {
int i;
for (i = 0; i < endByte - startByte; i++) {
dst[i] = (byte)((bytes[startByte + i] << shiftA) | (bytes[startByte + i + 1] >> shiftB));
}
if (i < dst.Length) {
dst[i] = (byte)(bytes[startByte + i] << shiftA);
}
}
dst[dst.Length - 1] &= (byte)(0xFF << ((dst.Length * 8) - length));
return dst;
}
}
public static class BitConverterBE {
public static ulong ToUInt64(byte[] value, int startIndex) {
return
((ulong)value[startIndex ] << 56) |
((ulong)value[startIndex + 1] << 48) |
((ulong)value[startIndex + 2] << 40) |
((ulong)value[startIndex + 3] << 32) |
((ulong)value[startIndex + 4] << 24) |
((ulong)value[startIndex + 5] << 16) |
((ulong)value[startIndex + 6] << 8) |
((ulong)value[startIndex + 7] );
}
public static uint ToUInt32(byte[] value, int startIndex) {
return
((uint)value[startIndex ] << 24) |
((uint)value[startIndex + 1] << 16) |
((uint)value[startIndex + 2] << 8) |
((uint)value[startIndex + 3] );
}
public static ushort ToUInt16(byte[] value, int startIndex) {
return (ushort)(
(value[startIndex ] << 8) |
(value[startIndex + 1] ));
}
public static byte[] GetBytes(ulong value) {
byte[] buff = new byte[8];
buff[0] = (byte)(value >> 56);
buff[1] = (byte)(value >> 48);
buff[2] = (byte)(value >> 40);
buff[3] = (byte)(value >> 32);
buff[4] = (byte)(value >> 24);
buff[5] = (byte)(value >> 16);
buff[6] = (byte)(value >> 8);
buff[7] = (byte)(value );
return buff;
}
public static byte[] GetBytes(uint value) {
byte[] buff = new byte[4];
buff[0] = (byte)(value >> 24);
buff[1] = (byte)(value >> 16);
buff[2] = (byte)(value >> 8);
buff[3] = (byte)(value );
return buff;
}
public static byte[] GetBytes(ushort value) {
byte[] buff = new byte[2];
buff[0] = (byte)(value >> 8);
buff[1] = (byte)(value );
return buff;
}
}
public static class BitConverterLE {
public static byte[] GetBytes(ulong value) {
byte[] buff = new byte[8];
buff[0] = (byte)(value );
buff[1] = (byte)(value >> 8);
buff[2] = (byte)(value >> 16);
buff[3] = (byte)(value >> 24);
buff[4] = (byte)(value >> 32);
buff[5] = (byte)(value >> 40);
buff[6] = (byte)(value >> 48);
buff[7] = (byte)(value >> 56);
return buff;
}
public static byte[] GetBytes(uint value) {
byte[] buff = new byte[4];
buff[0] = (byte)(value );
buff[1] = (byte)(value >> 8);
buff[2] = (byte)(value >> 16);
buff[3] = (byte)(value >> 24);
return buff;
}
public static byte[] GetBytes(ushort value) {
byte[] buff = new byte[2];
buff[0] = (byte)(value );
buff[1] = (byte)(value >> 8);
return buff;
}
}
现在实现 Audio Helper 类和接口:
interface IAudioWriter
{
void WriteChunk(byte[] chunk, uint timeStamp);
void Finish();
string Path { get; }
}
class AACWriter : IAudioWriter
{
string _path;
FileStream _fs;
int _aacProfile;
int _sampleRateIndex;
int _channelConfig;
public AACWriter(string path) {
_path = path;
_fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, 65536);
}
public void WriteChunk(byte[] chunk, uint timeStamp)
{
if (chunk.Length < 1) return;
if (chunk[0] == 0) { // Header
if (chunk.Length < 3) return;
ulong bits = (ulong)BitConverterBE.ToUInt16(chunk, 1) << 48;
_aacProfile = BitHelper.Read(ref bits, 5) - 1;
_sampleRateIndex = BitHelper.Read(ref bits, 4);
_channelConfig = BitHelper.Read(ref bits, 4);
if ((_aacProfile < 0) || (_aacProfile > 3))
throw new Exception("Unsupported AAC profile.");
if (_sampleRateIndex > 12)
throw new Exception("Invalid AAC sample rate index.");
if (_channelConfig > 6)
throw new Exception("Invalid AAC channel configuration.");
}
else { // Audio data
int dataSize = chunk.Length - 1;
ulong bits = 0;
// Reference: WriteADTSHeader from FAAC's bitstream.c
BitHelper.Write(ref bits, 12, 0xFFF);
BitHelper.Write(ref bits, 1, 0);
BitHelper.Write(ref bits, 2, 0);
BitHelper.Write(ref bits, 1, 1);
BitHelper.Write(ref bits, 2, _aacProfile);
BitHelper.Write(ref bits, 4, _sampleRateIndex);
BitHelper.Write(ref bits, 1, 0);
BitHelper.Write(ref bits, 3, _channelConfig);
BitHelper.Write(ref bits, 1, 0);
BitHelper.Write(ref bits, 1, 0);
BitHelper.Write(ref bits, 1, 0);
BitHelper.Write(ref bits, 1, 0);
BitHelper.Write(ref bits, 13, 7 + dataSize);
BitHelper.Write(ref bits, 11, 0x7FF);
BitHelper.Write(ref bits, 2, 0);
_fs.Write(BitConverterBE.GetBytes(bits), 1, 7);
_fs.Write(chunk, 1, dataSize);
}
}
public void Finish() {
_fs.Close();
}
public string Path {
get {
return _path;
}
}
}
现在您需要自己做的是,从第一个 AAC 文件中逐个读取块并写入它们,然后从第二个 AAC 文件中逐个读取块并将它们附加到中间文件。
注意,上面的代码是 C#,所以你必须使用 wrapping 来模拟 C# 的ref
效果,只需替换:
ref Type variable_name
和:
_<Type> variable_name