2013-05-09 3 views
3

Я пытаюсь выполнить некоторую обработку звука, я действительно придерживаюсь стереофонического преобразования в моно. Я смотрел в интернете, касаясь стереофонического преобразования.Преобразование аудио-стерео в аудио-байт

Насколько я знаю, я могу взять левый канал, правый канал, суммировать их и разделить на 2. Но когда я снова дам результат в WAV-файл, у меня появилось много шума переднего плана. Я знаю, что шум может быть вызван при обработке данных, там есть переполнение в байтовой переменной.

Это мой класс извлекал байт [] ломти данных из файла MP3:

общественного класса InputSoundDecoder {

private int BUFFER_SIZE = 128000; 
private String _inputFileName; 
private File _soundFile; 
private AudioInputStream _audioInputStream; 
private AudioFormat _audioInputFormat; 
private AudioFormat _decodedFormat; 
private AudioInputStream _audioInputDecodedStream; 

public InputSoundDecoder(String fileName) throws UnsuportedSampleRateException{ 
    this._inputFileName = fileName; 
    this._soundFile = new File(this._inputFileName); 
    try{ 
     this._audioInputStream = AudioSystem.getAudioInputStream(this._soundFile); 
    } 
    catch (Exception e){ 
     e.printStackTrace(); 
     System.err.println("Could not open file: " + this._inputFileName); 
     System.exit(1); 
    } 

    this._audioInputFormat = this._audioInputStream.getFormat(); 

    this._decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 1, 44100, false); 
    this._audioInputDecodedStream = AudioSystem.getAudioInputStream(this._decodedFormat, this._audioInputStream); 

    /** Supported sample rates */ 
    switch((int)this._audioInputFormat.getSampleRate()){ 
     case 22050: 
       this.BUFFER_SIZE = 2304; 
      break; 

     case 44100: 
       this.BUFFER_SIZE = 4608; 
      break; 

     default: 
      throw new UnsuportedSampleRateException((int)this._audioInputFormat.getSampleRate()); 
    } 

    System.out.println ("# Channels: " + this._decodedFormat.getChannels()); 
    System.out.println ("Sample size (bits): " + this._decodedFormat.getSampleSizeInBits()); 
    System.out.println ("Frame size: " + this._decodedFormat.getFrameSize()); 
    System.out.println ("Frame rate: " + this._decodedFormat.getFrameRate()); 

} 

public byte[] getSamples(){ 
    byte[] abData = new byte[this.BUFFER_SIZE]; 
    int bytesRead = 0; 

    try{ 
     bytesRead = this._audioInputDecodedStream.read(abData,0,abData.length); 
    } 
    catch (Exception e){ 
     e.printStackTrace(); 
     System.err.println("Error getting samples from file: " + this._inputFileName); 
     System.exit(1); 
    } 

    if (bytesRead > 0) 
     return abData; 
    else 
     return null; 
} 

}

Это означает, что каждый раз, когда я называю getSamples, его возвращает массив, подобный:

buff = {Lchannel, Rchannel, Lchannel, Rchannel, Lchannel, Rchannel, Lchannel, Rchannel ...}

Обработка рутина Конверсия в моно выглядит следующим образом:

byte[] buff = null; 
     while((buff = _input.getSamples()) != null){ 

      /** Convert to mono */ 
      byte[] mono = new byte[buff.length/2]; 

      for (int i = 0 ; i < mono.length/2; ++i){ 
       int left = (buff[i * 4] << 8) | (buff[i * 4 + 1] & 0xff); 
       int right = (buff[i * 4 + 2] <<8) | (buff[i * 4 + 3] & 0xff); 
       int avg = (left + right)/2; 
       short m = (short)avg; /*Mono is an average between 2 channels (stereo)*/ 
       mono[i * 2] = (byte)((short)(m >> 8)); 
       mono[i * 2 + 1] = (byte)(m & 0xff); 
      } 

}

и запись в файл WAV с помощью:

 public static void writeWav(byte [] theResult, int samplerate, File outfile) { 
     // now convert theResult into a wav file 
     // probably should use a file if samplecount is too big! 
     int theSize = theResult.length; 


     InputStream is = new ByteArrayInputStream(theResult); 
     //Short2InputStream sis = new Short2InputStream(theResult); 

     AudioFormat audioF = new AudioFormat(
       AudioFormat.Encoding.PCM_SIGNED, 
       samplerate, 
       16, 
       1,   // channels 
       2,   // framesize 
       samplerate, 
       false 
     ); 

     AudioInputStream ais = new AudioInputStream(is, audioF, theSize); 

     try { 
      AudioSystem.write(ais, AudioFileFormat.Type.WAVE, outfile); 
     } catch (IOException ioe) { 
      System.err.println("IO Exception; probably just done with file"); 
      return; 
     } 


    } 

С 44100 как частота дискретизации.

Примите во внимание, что на самом деле байт [] массив, который я получил это уже ИКМ, так mp3 -> преобразования ИКМ это делается путем указания

this._decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 1, 44100, false); 
this._audioInputDecodedStream = AudioSystem.getAudioInputStream(this._decodedFormat, this._audioInputStream); 

В I сказал, при записи в Wav-файл у меня много шума. Я притворяюсь, что применим к каждому фрагменту байта БПФ, но я думаю, из-за шумного звука результат не правильный.

Потому что я беру две песни, одна из них - это 20-секундный урожай от другой, и при сравнении результата урожая fft с исходным 20-секундным подмножеством это совсем не совпадает.

Я думаю, что это неправильное преобразование стерео-> моно.

Надежда кто-то знает что-то об этом,

С уважением.

+0

Если это вызвано переполнением, почему бы не разделить на 2, а затем суммировать? – James

+0

Возможно, вы ошиблись в представлении данных.Попробуйте сделать что-то вроде чтения и записи без преобразования или, еще лучше, поместите через него известный чистый источник данных (возможно, прямоугольную волну, используя только 2 различных значения амплитуды) и исследуйте необработанные байты вывода. Имея небольшой опыт, можно быстро распознать типы проблем, если графический сигнал в аудиопрограмме. –

+0

Если я не конвертирую, все, что у меня есть из mp3-файла, это необработанные закодированные байты. Преобразование - это необязательный шаг, это нужно сделать, чтобы иметь реальные значения звука в массиве. Разделение и суммирование имеют тот же результат ... – Mario

ответ

6

Как указано в комментариях, утверждение может быть ошибочным. Кроме того, преобразование в подписанное короткое и смещение может привести к тому, что первый байт будет 0xFF.

Try:

int HI = 0; int LO = 1; 
int left = (buff[i * 4 + HI] << 8) | (buff[i * 4 + LO] & 0xff); 
int right = (buff[i * 4 + 2 + HI] << 8) | (buff[i * 4 + 2 + LO] & 0xff); 
int avg = (left + right)/2; 
mono[i * 2 + HI] = (byte)((avg >> 8) & 0xff); 
mono[i * 2 + LO] = (byte)(avg & 0xff); 

Затем переключитесь значения HI и LO, чтобы увидеть, если он становится лучше.

+2

Спасибо большое !, проблема была в отношении endian !, Я использовал HI = 1, LO = 0 и работал как шарм! – Mario

Смежные вопросы