2014-09-10 2 views
3

Я пытаюсь разбить аудиофайл на несколько частей.Разделить аудиофайлы на куски

Дело в том, что у меня есть массив байтов, и я хотел бы разбить wav-файл на некоторые случайные фрагменты (например, 3).

Конечно, я знаю, что я не могу сделать что-то подобное. Но есть ли у кого-нибудь идея о том, как это сделать?

byte[] result = stream.ToArray(); 
byte[] testing = new byte[44]; 

for (int ix = 0; ix < testing.Length; ix++) 
{ 
    testing[ix] = result[ix]; 
} 

System.IO.File.WriteAllBytes("yourfilepath_" + System.Guid.NewGuid() + ".wav", testing); 

Я хотел бы делать построить это решение в C#, но я слышал, что есть Lib называется Sox, и я могу разделить с молчаливой щелью, как это:

sox in.wav out.wav silence 1 0.5 1% 1 5.0 1% : newfile : restart 

Но каждый раз, когда я запускаю эту команду, генерируется только один файл. (аудиофайл длится 5 секунд, и каждый разбитый файл должен иметь что-то за секунду).

Каков наилучший способ для этого?

спасибо!

ответ

3

EDIT

С SOX:

string sox = @"C:\Program Files (x86)\sox-14-4-1\sox.exe"; 
string inputFile = @"D:\Brothers Vibe - Rainforest.mp3"; 
string outputDirectory = @"D:\splittest"; 
string outputPrefix = "split"; 

int[] segments = { 10, 15, 30 }; 

IEnumerable<string> enumerable = segments.Select(s => "trim 0 " + s.ToString(CultureInfo.InvariantCulture)); 
string @join = string.Join(" : newfile : ", enumerable); 
string cmdline = string.Format("\"{0}\" \"{1}%1n.wav" + "\" {2}", inputFile, 
    Path.Combine(outputDirectory, outputPrefix), @join); 

var processStartInfo = new ProcessStartInfo(sox, cmdline); 
Process start = System.Diagnostics.Process.Start(processStartInfo); 

Если SOX жалуется libmad (для MP3): скопировать библиотеки DLL рядом с ним, см here

В качестве альтернативы вы можете использовать FFMPEG в таким же образом:

ffmpeg -ss 0 -t 30 -i "Brothers Vibe - Rainforest.mp3" "Brothers Vibe - Rainforest.wav" 

(see the docs для всех деталей)


Вы можете сделать это легко с BASS.NET:

Для кода ниже вы передаете:

  • имя входного файла
  • желательно продолжительность для каждого сегмента
  • Выходной каталог
  • префикса для использования для каждого файла сегмента

Метод проверяет, является ли достаточно долго для указанных сегментов файла, если да, то он будет разрезать файл на WAVs с той же частотой дискретизации, каналы, бит глубина.

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Windows.Forms; 
using Un4seen.Bass; 
using Un4seen.Bass.Misc; 

namespace WindowsFormsApplication2 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      if (!Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero)) 
       throw new InvalidOperationException("Couldn't initialize BASS"); 

      string fileName = @"D:\Brothers Vibe - Rainforest.mp3"; 
      var segments = new double[] {30, 15, 20}; 
      string[] splitAudio = SplitAudio(fileName, segments, "output", @"D:\split"); 
     } 

     private static string[] SplitAudio(string fileName, double[] segments, string prefix, string outputDirectory) 
     { 
      if (fileName == null) throw new ArgumentNullException("fileName"); 
      if (segments == null) throw new ArgumentNullException("segments"); 
      if (prefix == null) throw new ArgumentNullException("prefix"); 
      if (outputDirectory == null) throw new ArgumentNullException("outputDirectory"); 
      int i = Bass.BASS_StreamCreateFile(fileName, 0, 0, 
       BASSFlag.BASS_STREAM_PRESCAN | BASSFlag.BASS_STREAM_DECODE); 
      if (i == 0) 
       throw new InvalidOperationException("Couldn't create stream"); 

      double sum = segments.Sum(); 

      long length = Bass.BASS_ChannelGetLength(i); 
      double seconds = Bass.BASS_ChannelBytes2Seconds(i, length); 
      if (sum > seconds) 
       throw new ArgumentOutOfRangeException("segments", "Required segments exceed file duration"); 
      BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(i); 

      if (!Directory.Exists(outputDirectory)) Directory.CreateDirectory(outputDirectory); 

      int index = 0; 
      var list = new List<string>(); 
      foreach (double segment in segments) 
      { 
       double d = segment; 
       long seconds2Bytes = Bass.BASS_ChannelSeconds2Bytes(i, d); 
       var buffer = new byte[seconds2Bytes]; 
       int getData = Bass.BASS_ChannelGetData(i, buffer, buffer.Length); 
       string name = string.Format("{0}_{1}.wav", prefix, index); 
       string combine = Path.Combine(outputDirectory, name); 
       int bitsPerSample = info.Is8bit ? 8 : info.Is32bit ? 32 : 16; 
       var waveWriter = new WaveWriter(combine, info.chans, info.freq, bitsPerSample, true); 
       waveWriter.WriteNoConvert(buffer, buffer.Length); 
       waveWriter.Close(); 
       list.Add(combine); 
       index++; 
      } 
      bool free = Bass.BASS_StreamFree(i); 

      return list.ToArray(); 
     } 
    } 
} 

TODO

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

Примечания

BASS.NET имеет экран скринсейвера, но вы можете запросить бесплатный регистрационный серийный номер на своем веб-сайте.

Обратите внимание: установите BASS.NET, затем скопируйте файл bass.dll из базового пакета рядом с вашим EXE. Кроме того, вы можете использовать практически любые аудиоформаты, видеть их сайт для плагинов форматов и как их загрузить (BASS_PluginLoad).

+0

Спасибо Ayve, ссылка была полезна =) ... но я должен сделать это, чтобы создать что-то на работе ... can't использовать бесплатно BASS =/ – Crasher

+0

см. Мое редактирование с помощью SOX! – Aybe

+0

Спасибо Aybe! Это было действительно полезно =) знаете ли вы, если ffmpeg позволяет мне разделять файлы по тишине? – Crasher

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