2012-10-04 3 views
6

का उपयोग कर 2 एएसी फाइलों को संयोजित करें, मैं 2 एएसी फ़ाइलों को एक में गठबंधन करने की कोशिश कर रहा हूं, मुझे पता चला कि एएसी फाइलों में - हेडर तत्व एफएफ 8 बाइट तक मौजूद है, और उसके बाद अगले 4 बाइट्स में डेटा की लंबाई होती है एएसी मैंने 1 हेडर सरणी बनाए रखने की कोशिश की, 2 एएसी फाइलों का आकार जोड़ें, और फिर दो फ़ाइलों के डेटा बफर को एक के बाद एक जोड़ें।जावा

परिणामस्वरूप फ़ाइल केवल पहली एएसी फ़ाइल खेली। कोड स्निपेट यहाँ है।

FileInputStream fs = new FileInputStream("./res/after.aac"); 

dis = new DataInputStream(fs); 
headerData = new byte[0xFF8]; 
dis.read(headerData); 


int lengthTotal = dis.readInt(); 
System.out.println("Length of After == "+lengthTotal); 
dis.readInt(); 


data = new byte[dis.available()]; 

dis.readFully(data); 
dis.close(); 
dis = null; 
fs.close(); 
fs = null; 


fs = new FileInputStream("./res/continue.aac"); 
dis = new DataInputStream(fs); 

dis.skipBytes(0xFF8); 

int length = dis.readInt(); 
System.out.println("Length of Ahead == "+length); 
lengthTotal = lengthTotal + length -8; 
System.out.println("Total Length== "+lengthTotal); 
dis.readInt(); 
newData = new byte[dis.available()]; 
dis.read(newData); 

FileOutputStream fos = new FileOutputStream("./res/combine.aac"); 
DataOutputStream dos = new DataOutputStream(fos); 

dos.write(headerData); 
dos.writeInt(lengthTotal); 
dos.writeBytes("mdat"); 
dos.write(data); 
dos.write(newData); 

मैं जानता हूँ कि 56 वें बाइट में एएसी फ़ाइल की समय अवधि के बारे में जानकारी है कि वहाँ है, लेकिन मैं यह पता लगाने में सक्षम नहीं होने रहा हूँ। क्या कोई मुझे यहां से बाहर निकलने में मदद कर सकता है?

+0

मैं वही कोशिश कर रहा हूं ... क्या आपने इसे ठीक किया? कोई समाधान? –

उत्तर

1

ठीक है, मैं आपको यह नहीं बता सकता कि आप क्या गलत कर रहे हैं। लेकिन मैं आपको बता सकता हूं कि आप क्या करना चाहते हैं।

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; 
    } 
} 

अब लागू ऑडियो सहायक वर्ग और इंटरफ़ेस::

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; 
     } 
    } 
} 

अब आप से एक के बाद खुद ही करने के लिए किया जाता है, मात्रा एक पढ़ा की जरूरत है क्या

सबसे पहले एक सामान्य हेल्पर कार्य बनाने पहली एएसी फ़ाइल और उन्हें लिखें, उसके बाद, दूसरी एएसी फ़ाइल से एक-एक करके भाग पढ़ें और उन्हें इंटरमीडिएट फ़ाइल में जोड़ें।

ध्यान दें, इसके बाद के संस्करण कोड सी # है, तो आप रैपिंग उपयोग करने के लिए सी # के ref प्रभाव अनुकरण करने के लिए, बस की जगह नहीं होगी:

साथ
ref Type variable_name 

:

_<Type> variable_name 
+0

यहां तक ​​कि यह अभी भी पर्याप्त नहीं होगा, क्योंकि MPEG4 मेटाडेटा का एक गुच्छा है (जैसे 'stsz 'नमूना आकार तालिका) जिसे बुद्धिमानी से जोड़ा जाना है। – duskwuff

+0

आप जो सुझाव दे रहे हैं वह एमपी 4 कंटेनर के दायरे में आता है। प्रत्येक खंड में 'ADTSHeader' डीकोडर के लिए सही ढंग से ऑडियो को डीकोड करने के लिए पर्याप्त जानकारी प्रदान करता है, जो एएसी कच्ची फ़ाइल है। @duskwuff –

+0

नमूना कोड में 'mdat" 'का संदर्भ मुझे लगता है कि यह वास्तव में गलत एक्सटेंशन के साथ एक एमपीईजी 4 है। – duskwuff

1

मैं तुम्हें सुझाव है jaad लाइब्रेरी में एएसी फाइलों को कैसे पार्स किया गया है, इस पर एक नज़र डालने के लिए, विशेष रूप से दिलचस्प एडीटीएस हैंडलिंग कोड here और एडीआईएफ हेडर पार्सिंग here है।