Skip to content

Instantly share code, notes, and snippets.

@chgeuer
Last active December 20, 2019 11:49
Show Gist options
  • Save chgeuer/92ee4798be7f1c640ebd3fd4ac1c04ba to your computer and use it in GitHub Desktop.
Save chgeuer/92ee4798be7f1c640ebd3fd4ac1c04ba to your computer and use it in GitHub Desktop.
Ogg2Wav
package com.microsoft.cse;
import java.io.*;
import java.nio.file.*;
public class Main {
private static class Pump implements Runnable {
private final InputStream is;
private final OutputStream os;
Pump(InputStream is, OutputStream os) {
this.is = is;
this.os = os;
}
@Override
public void run() {
byte buffer[] = new byte[1024 * 1024];
int numRead;
try {
while ((numRead = this.is.read(buffer)) != -1) {
os.write(buffer, 0, numRead);
}
this.os.close();
} catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
}
public static Thread start(InputStream is, OutputStream os) {
var t = new Thread(new Pump(is, os));
t.start();
return t;
}
};
public static void main(String[] args) throws Exception {
String sourceFileName = "C:\\Users\\chgeuer\\Music\\malte\\long-test.ogg";
String outputFile = "C:\\Users\\chgeuer\\Music\\malte\\testing.wav";
File inputFile = new File(sourceFileName);
byte[] fileContent = Files.readAllBytes(inputFile.toPath());
Process process = Runtime.getRuntime().exec(
"ffmpeg.exe -i - -f wav -flags +bitexact -c:a pcm_s16le -ar 16000 -ac 1 -");
InputStream oggStream = new ByteArrayInputStream(fileContent);
OutputStream processStdinStream = process.getOutputStream();
Thread threadIn = Pump.start(oggStream, processStdinStream);
InputStream processStdoutStream = process.getInputStream();
ByteArrayOutputStream wavStream = new ByteArrayOutputStream();
Thread threadOut = Pump.start(processStdoutStream, wavStream);
InputStream processStderrStream = process.getErrorStream();
ByteArrayOutputStream loggingStream = new ByteArrayOutputStream();
Thread threadErr = Pump.start(processStderrStream, loggingStream);
threadIn.join();
int exitCode = process.waitFor();
threadOut.join();
threadErr.join();
try(var outPutFileStream = new FileOutputStream(new File(outputFile))) {
byte[] wavByteArray = wavStream.toByteArray();
long l1 = wavByteArray.length - 8;
wavByteArray[4] = (byte) ((l1 >> 0) & 0xff);
wavByteArray[5] = (byte) ((l1 >> 8) & 0xff);
wavByteArray[6] = (byte) ((l1 >> 16) & 0xff);
wavByteArray[7] = (byte) ((l1 >> 24) & 0xff);
long l2 = wavByteArray.length - 78;
wavByteArray[0x4a] = (byte) ((l2 >> 0) & 0xff);
wavByteArray[0x4b] = (byte) ((l2 >> 8) & 0xff);
wavByteArray[0x4c] = (byte) ((l2 >> 16) & 0xff);
wavByteArray[0x4d] = (byte) ((l2 >> 24) & 0xff);
outPutFileStream.write(wavByteArray);
}
System.out.println("Exit Code: " + exitCode);
System.out.println(new String(loggingStream.toByteArray()));
}
}
namespace lib
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
public static class ProcessExtensions
{
public class ProcessResult
{
public byte[] Stdout { get; set; }
public byte[] Stderr { get; set; }
public int? ExitCode { get; set; }
}
public static Task<ProcessResult> RunAsync(string filename, string arguments, Stream stdinStream)
{
var processStartInfo = new ProcessStartInfo
{
FileName = filename,
Arguments = arguments,
RedirectStandardInput = stdinStream != null && stdinStream.CanRead,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
return processStartInfo.RunAsync(stdinStream);
}
public static Task<ProcessResult> RunAsync(this ProcessStartInfo startInfo, Stream stdinStream) =>
startInfo.RunAsync(TimeSpan.Zero, stdinStream);
public static async Task<ProcessResult> RunAsync(this ProcessStartInfo startInfo, TimeSpan timeout, Stream stdinStream)
{
using var stdout = new MemoryStream();
using var stderr = new MemoryStream();
using var process = new Process
{
StartInfo = startInfo,
EnableRaisingEvents = true
};
var tasks = new List<Task>();
var processExitEvent = new TaskCompletionSource<bool>();
tasks.Add(processExitEvent.Task);
process.Exited += (sender, args) => { Task.Run(() => { processExitEvent.TrySetResult(true); }); };
var startSuccess = process.Start();
if (!startSuccess)
{
return new ProcessResult { Stdout = stdout.ToArray(), Stderr = stderr.ToArray(), ExitCode = process.ExitCode };
}
if (process.StartInfo.RedirectStandardInput && stdinStream != null && stdinStream.CanRead)
{
tasks.Add(stdinStream.CopyToAndCloseAsync(process.StandardInput.BaseStream));
}
if (process.StartInfo.RedirectStandardOutput)
{
tasks.Add(process.StandardOutput.BaseStream.CopyToAndCloseAsync(stdout));
}
if (process.StartInfo.RedirectStandardError)
{
tasks.Add(process.StandardError.BaseStream.CopyToAndCloseAsync(stderr));
}
var processCompletionTask = Task.WhenAll(tasks);
Task<Task> awaitingTask = (timeout > TimeSpan.Zero)
? Task.WhenAny(processCompletionTask, Task.Delay(timeout))
: Task.WhenAny(processCompletionTask);
var finishedTask = await awaitingTask;
if (finishedTask == processCompletionTask)
{
return new ProcessResult { Stdout = stdout.ToArray(), Stderr = stderr.ToArray(), ExitCode = process.ExitCode };
}
else
{
try { process.Kill(); } catch { }
return new ProcessResult { Stdout = stdout.ToArray(), Stderr = stderr.ToArray(), ExitCode = null };
}
}
private static async Task CopyToAndCloseAsync(this Stream from, Stream to)
{
await from.CopyToAsync(to);
to.Close();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment