How to convert a sound file from wav to ulaw? - audio

I need a utility to convert from wav to ulaw for my IVR. What third-party software can I use?

This is the opposite of what you are trying to do, but I thought it could be helpful to someone. Here is an exmple method that will convert an 8-bit uLaw encoded binary file into a 16-bit WAV file using built-in Java methods.
public static void convertULawFileToWav(String filename) {
File file = new File(filename);
if (!file.exists())
return;
try {
long fileSize = file.length();
int frameSize = 160;
long numFrames = fileSize / frameSize;
AudioFormat audioFormat = new AudioFormat(Encoding.ULAW, 8000, 8, 1, frameSize, 50, true);
AudioInputStream audioInputStream = new AudioInputStream(new FileInputStream(file), audioFormat, numFrames);
AudioSystem.write(audioInputStream, Type.WAVE, new File("C:\\file.wav"));
} catch (IOException e) {
e.printStackTrace();
}
}

Related

How to save a microedition.lcdui.Image object into storage?

How can you save an Image (microedition.lcdui.Image) object into storage?
I have this Image object:
Image outImg; //Contains image data
I tried the code below to save it to storage but without success:
int[] rgb = new int[240*320];
outImg.getRGB(rgb, 0, 240, 0, 0, 240, 320);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
dout.writeInt(240);
dout.writeInt(320);
for (int i = 0; i < rgb.length; i++) {
dout.writeInt(rgb[i]);
}
bytes = bout.toByteArray();
FileConnection fcOut = (FileConnection) Connector.open("file:///root1/img.png", Connector.READ_WRITE);
if (!fcOut.exists()) {
fcOut.create();
}
DataOutputStream out = fcOut.openDataOutputStream();
out.write(bytes);
I searched for a solution but didn't find anything useful. How can I achieve this?
Alternatively, is there a way I can convert an Image object to a byte array? So I can use DataOutputStream to write the byte array to memory.

Handling a WebRTC byte[] stream?

I'm basically trying to record audio chunks from a webrtc stream, I've been able to send the binary data with help of this resource HTML Audio Capture streaming to Node.js.
Im using netty-socketio, as this library plays well with socket-io on the client side.
Here are my server endpoints:
server.addEventListener("audio-blob", byte[].class, (socketIOClient, bytes, ackRequest) -> {
byteArrayList.add(bytes);
});
server.addEventListener("audio-blob-end", Object.class, (socket, string, ackRequest) -> {
ByteArrayInputStream in = new ByteArrayInputStream(byteArrayList.getArray());
AudioInputStream audiIn = new AudioInputStream(in, getAudioFormat(), 48000l);
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
File wavFile = new File("RecordAudio.wav");
AudioSystem.write(audiIn,fileType,wavFile);
});
The format settings:
public static AudioFormat getAudioFormat() {
float sampleRate = 48000;
int sampleSizeInBits = 8;
int channels = 2;
boolean signed = true;
boolean bigEndian = true;
AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits,
channels, signed, bigEndian);
return format;
}
Im using this class to collect the byte arrays (and yes I know the risk with this solution)
class ByteArrayList {
private List<Byte> bytesList;
public ByteArrayList() {
bytesList = new ArrayList<Byte>();
}
public void add(byte[] bytes) {
add(bytes, 0, bytes.length);
}
public void add(byte[] bytes, int offset, int length) {
for (int i = offset; i < (offset + length); i++) {
bytesList.add(bytes[i]);
}
}
public int size(){
return bytesList.size();
}
public byte[] getArray() {
byte[] bytes = new byte[bytesList.size()];
for (int i = 0; i < bytesList.size(); i++) {
bytes[i] = bytesList.get(i);
}
return bytes;
}
}
The generated wav file only plays noise though, no recording is present. What am I doing wrong?
When Google:ing around for answers I stumbled upon this resource how to save a wav file
What I was doing wrong is that I had a fixed size on the AudioInputstream constructor parameter:
new AudioInputStream(in, getAudioFormat(), 48000l)
changed it to the:
new AudioInputStream(in, getAudioFormat(),byteArrayList.getArray().length);

wma audio stream to mp3 stream using NAudio c#

My task is to convert wma audio stream to mp3 stream using NAudio and Lame. The below code is working fine with file name but I want it to be done with memory stream. I search in NAudio there is no method for reading wma audio stream. Is it possible with NAudio?
public static byte[] ConvertWmaToMp3(uint bitrate = 128)
{
FileStream fs = new FileStream("..\\sample.wma", FileMode.Open, FileAccess.Read);
var ws = new NAudio.WindowsMediaFormat.WMAFileReader(fs.Name);
// Setup encoder configuration
WaveLib.WaveFormat fmt = new WaveLib.WaveFormat(ws.WaveFormat.SampleRate, 16, ws.WaveFormat.Channels);
Yeti.Lame.BE_CONFIG beconf = new Yeti.Lame.BE_CONFIG(fmt, bitrate);
// Encode WAV to MP3
int blen = ws.WaveFormat.AverageBytesPerSecond;
byte[] buffer = new byte[blen];
byte[] mp3data = null;
using (MemoryStream mp3strm = new MemoryStream())
using (Mp3Writer mp3wri = new Mp3Writer(mp3strm, fmt, beconf))
{
int rc;
while ((rc = ws.Read(buffer, 0, blen)) > 0)
{
mp3wri.Write(buffer, 0, rc);
}
mp3data = mp3strm.ToArray();
}
return mp3data;
}
Currently the WMAFileReader class doesn't support reading data from a stream. The WMA APIs support reading WMA from an IStream so it is definitely possible.
If you want to implement streaming yourself you'll need to grab the source code for WmaFileReader and WmaStream from CodePlex, and use them as templates for your modified classes.
First thing you'll need is a wrapper class that provides a COM IStream interface to a .NET Stream. Here's a simple one:
public class InteropStream : IStream, IDisposable
{
public readonly Stream intern;
public InteropStream(Stream strm)
{
intern = strm;
}
~InteropStream()
{
Dispose(true);
}
public void Dispose()
{
Dispose(false);
}
protected void Dispose(bool final)
{
if (final)
intern.Dispose();
}
#region IStream Members
public void Clone(out IStream ppstm)
{
ppstm = null;
}
public void Commit(int grfCommitFlags)
{
intern.Flush();
}
readonly byte[] buffer = new byte[4096];
public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt32(pcbRead, 0);
if (pcbWritten != IntPtr.Zero)
Marshal.WriteInt32(pcbWritten, 0);
}
public void LockRegion(long libOffset, long cb, int dwLockType)
{ }
public void Read(byte[] pv, int cb, IntPtr pcbRead)
{
int rc = intern.Read(pv, 0, cb);
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt32(pcbRead, rc);
}
public void Revert()
{ }
public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
long origin = 0;
if (dwOrigin == 1) // STREAM_SEEK_CUR
origin = intern.Position;
else if (dwOrigin == 2) // STREAM_SEEK_END
origin = intern.Length;
long pos = origin + dlibMove;
intern.Position = pos;
if (plibNewPosition != IntPtr.Zero)
Marshal.WriteInt64(plibNewPosition, pos);
}
public void SetSize(long libNewSize)
{ }
public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag)
{
var res = new System.Runtime.InteropServices.ComTypes.STATSTG();
res.type = 2; // STGTY_STREAM
res.cbSize = intern.Length;
pstatstg = res;
}
public void UnlockRegion(long libOffset, long cb, int dwLockType)
{ }
public void Write(byte[] pv, int cb, IntPtr pcbWritten)
{ }
#endregion
}
Next copy the WmaStream code to a new namespace in your project and add the following code to the top of the class:
InteropStream interopStrm = null;
public WmaStream(Stream fileStream)
: this(fileStream, null)
{ }
public WmaStream(Stream fileStream, WaveFormat OutputFormat)
{
interopStrm = new InteropStream(fileStream);
m_reader = WM.CreateSyncReader(WMT_RIGHTS.WMT_RIGHT_NO_DRM);
try
{
IWMSyncReader2 rdr = m_reader as IWMSyncReader2;
rdr.OpenStream(interopStrm);
Init(OutputFormat);
}
catch
{
try
{
m_reader.Close();
}
catch
{
}
m_reader = null;
throw;
}
}
Do the same with WmaFileReader and the following code:
public WMAFileReader(Stream wmaStream)
{
m_wmaStream = new WmaStream2(wmaStream);
m_waveFormat = m_wmaStream.Format;
}
Now you can create an instance of your modified WmaFileReader using either a filename or a Stream instance - MemoryStream, FileStream, etc. The Stream instance needs to be readable and seekable.
I've tried the above on a few random WMA files I found on my computer, loaded into MemoryStream or using FileStream, and it works as I expected it to.
Presumably Mark is working on adding this functionality to the NAudio.Wma package, so consider this an interim fix until NAudio supports it.
The easiest way to convert WMA to MP3 with NAudio is to use the Media Foundation based classes. If you are on Windows 8 and above, and MP3 encoder should be available.
using (var reader = new MediaFoundationReader("test.wma"))
{
MediaFoundationEncoder.EncodeToMp3(reader, "test.mp3");
}
On systems without an MP3 encoder, I tend to use LAME.exe and stream the input audio through stdin. See my article here for more info on this approach.

Deflate - Inflate errors. Causing "incorrect header check" errors

I am working on implementing a SAMLSLO through HTTP-REDIRECT binding mechanism. Using deflate-inflate tools gives me a DataFormatException with incorrect header check.
I tried this as a stand-alone. Though I did not get DataFormatException here I observed the whole message is not being returned.
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
public class InflateDeflate {
public static void main(String[] args) {
String source = "This is the SAML String";
String outcome=null;
byte[] bytesource = null;
try {
bytesource = source.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
int byteLength = bytesource.length;
Deflater compresser = new Deflater();
compresser.setInput(bytesource);
compresser.finish();
byte[] output = new byte[byteLength];
int compressedDataLength = compresser.deflate(output);
outcome = new String(output);
String trimmedoutcome = outcome.trim();
//String trimmedoutcome = outcome; // behaves the same way as trimmed;
// Now try to inflate it
Inflater decompresser = new Inflater();
decompresser.setInput(trimmedoutcome.getBytes());
byte[] result = new byte[4096];
int resultLength = 0;
try {
resultLength = decompresser.inflate(result);
} catch (DataFormatException e) {
e.printStackTrace();
}
decompresser.end();
System.out.println("result length ["+resultLength+"]");
String outputString = null;
outputString = new String(result, 0, resultLength);
String returndoc = outputString;
System.out.println(returndoc);
}
}
Surprisingly I get the result as [22] bytes, the original is [23] bytes and the 'g' is missing after inflating.
Am I doing something fundamentally wrong here?
Java's String is a CharacterSequence (a character is 2 bytes). Using new String(byte[]) may not correctly convert your byte[] to a String representation. At least you should specify a character encoding new String(byte[], "UTF-8") to prevent invalid character conversions.
Here's an example of compressing and decompressing:
import java.util.zip.Deflater;
import java.util.zip.InflaterInputStream;
...
byte[] sourceData; // bytes to compress (reuse byte[] for compressed data)
String filename; // where to write
{
// compress the data
Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION);
deflater.setInput(sourceData);
deflater.finish();
int compressedSize = deflater.deflate(data, 0, sourceData.length, Deflater.FULL_FLUSH);
// write the data
OutputStream stream = new FileOutputStream(filename);
stream.write(data, 0, compressedSize);
stream.close();
}
{
byte[] uncompressedData = new byte[1024]; // where to store the data
// read the data
InputStream stream = new InflaterInputStream(new FileInputStream(filename));
// read data - note: may not read fully (or evenly), read from stream until len==0
int len, offset = 0;
while ((len = stream.read(uncompressedData , offset, uncompressedData .length-offset))>0) {
offset += len;
}
stream.close();
}

image compress process get out of memory error

I'm running a multi thread image compressing process. The original file is 1280x
960 high resolution PNG file, about 1800KB. I need compress to <70KB JPEG file. When I process few vehicles, the process runs fine. when I process over 20 vehicles, I start to get out of memory error. Here is the code.
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
int j;
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for (j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}
public static void SaveAsJpg(string inFilePath = null, string outputFileName = null, long compression = 70, long quality = 70)
{
System.Drawing.Image orgimage = System.Drawing.Image.FromFile(inFilePath);
var imgIn = new Bitmap(orgimage);
var imgOut = new Bitmap(imgIn.Width, imgIn.Height);
Graphics g = Graphics.FromImage(imgOut);
g.Clear(Color.White);
g.DrawImage(imgIn, 0, 0, imgIn.Width, imgIn.Height);
EncoderParameters encoding = new EncoderParameters(2);
encoding.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, compression);
encoding.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
ImageCodecInfo myImageCodecInfo = GetEncoderInfo("image/jpeg");
imgOut.Save(outputFileName, myImageCodecInfo, encoding);
}
Thanks in advance for any suggestion.
I think you need to dispose the graphic objects before leaving the method.
g.Dispose();
orgiImage.Dispose();
imgIn.Dispose();
imgOut.Dispose();
Disposing System.drawing objects

Resources