Convert ogg audio file to opus audio file - c#

I am recording ogg file in Html5. It is recording fine. But i want to convert OGG file OPUS format file. I have tried so many libraries which is not working as expected.
The following code returning error like below,
The frame size must be one of the following: 2.5, 5, 10, 20, 40 or 60.
Parameter name: length.
using (FileStream fileIn = new FileStream(#"C:\Users\Downloads\1.ogg", FileMode.Open))
using (MemoryStream pcmStream = new MemoryStream())
{
short[] packets = new short[0];
var decoder = Concentus.Structs.OpusDecoder.Create(48000, 2);
var oggIn = new Concentus.Oggfile.OpusOggReadStream(decoder, fileIn);
while (oggIn.HasNextPacket)
{
short[] packet = oggIn.DecodeNextPacket();
if (packet != null)
{
for (int i = 0; i < packet.Length; i++)
{
var oggbytes = BitConverter.GetBytes(packet[i]);
pcmStream.Write(bytes, 0, bytes.Length);
}
if (packets != null && packets.Length > 0)
Combine(packets, packet);
else
{
packets = new short[packet.Length];
packets = packet;
}
}
}
pcmStream.Position = 0;
using (var memoryStream = new MemoryStream())
{
pcmStream.CopyTo(memoryStream);
var encoder = new OpusDotNet.OpusEncoder(OpusDotNet.Application.Audio, 48000, 2);
opbytes = new byte[packets.Length];
var obytes = encoder.Encode(memoryStream.ToArray(), packets.Length, out int encodedLength);
System.IO.File.WriteAllBytes(#"C:\Users\Downloads\new.opus", memoryStream.ToArray());
}
}
Please help me to convert OGG audio file to OPUS audio file in c#.
Thanks in advance,
Mani

Related

How to join mp3 and wav files using naudio to byte buffer c# MVC?

I found a lot of articles about how to join mp3 or wav files,but i didn't find nothing about how to join audio files of different types.I want to play wav file then mp3 file,one after another.
I tried to convert wav file to mp3 by using.
private static MemoryStream ConvertWavToMp3(string path)
{
if (File.Exists(path))
{
MemoryStream stream = new MemoryStream();
using (WaveFileReader rdr = new WaveFileReader(path))
using (LameMP3FileWriter wtr = new LameMP3FileWriter(stream, rdr.WaveFormat, 320))
{
rdr.CopyTo(wtr);
return stream;
}
}
else
{
return null;
}
}
}
I get bytes from mp3 file by following code.
private static MemoryStream GetBytesFromMp3(string path)
{
string storageName = path.Substring(path.IndexOf("\\\\") + 2, path.IndexOf("\\", 3) - path.IndexOf("\\\\") - 2);
string networkShare = path.Substring(0, path.LastIndexOf("\\"));
NetworkCredential credentials = new NetworkCredential(ConfigurationManager.AppSettings[storageName + "_User"], ConfigurationManager.AppSettings[storageName + "_Pass"]);
using (new NetworkConnection(networkShare, credentials))
{
if (File.Exists(path))
{
using (Mp3FileReader rdr = new Mp3FileReader(path,FileMode.OpenOrCreate))
{
byte[] result = new byte[rdr.Length];
rdr.Read(result, 0, result.Length);
int a = result.Max();
MemoryStream stream = new MemoryStream(result);
return stream;
}
}
else
{
return null;
}
}
}
and and then merge them
by
public static byte[] JoinFiles(List<FileWeb> files)
{
MemoryStream output = new MemoryStream();
int offset = 0;
foreach (FileWeb file in files)
{
MemoryStream mp3Data;
string fullPath = file.FilePath + "\\" + file.FileName;
if (file.FileName.EndsWith("wav"))
{
mp3Data = ConvertWavToMp3(fullPath);
}
else
{
mp3Data = GetBytesFromMp3(fullPath);
}
if (mp3Data != null)
{
byte[] buffer = mp3Data.ToArray();
output.Write(buffer, offset, buffer.Length - offset);
offset = 4;
}
}
return output.ToArray();
}
But it didn't work.It plays only first part.If i use this code.
public static void Combine(string[] inputFiles, Stream output)
{
foreach (string file in inputFiles)
{
Mp3FileReader reader = new Mp3FileReader(stream);
if ((output.Position == 0) && (reader.Id3v2Tag != null))
{
output.Write(reader.Id3v2Tag.RawData, 0, reader.Id3v2Tag.RawData.Length);
}
Mp3Frame frame;
while ((frame = reader.ReadNextFrame()) != null)
{
output.Write(frame.RawData, 0, frame.RawData.Length);
}
}
}
at Mp3FileReader reader = new Mp3FileReader(stream) i get error no mp3 header found.
Do not convert anything to MP3. Just create appropriate reader for given file (WaveFileReader for wav and Mp3FileReader for mp3). Both classes derives from WaveStream which provides Read method. Use that method to retrieve uncompressed data. Now you can easily merge two streams. Of course WaveFormat must match.
But you don't need to reinvent wheel. There is built in concatenation mechanism.
var wavReader = new WaveFileReader ("file.wav");
var mp3Reader = new Mp3FileReader ("file.mp3");
// convert to different interface
var wavProvider = wavReader.ToSampleProvider ();
var mp3Provider = mp3Reader.ToSampleProvider ();
// Must all share the same sample rate and channel count
var merged = new ConcatenatingSampleProvider (new[] { wavProvider, mp3Provider });
var output = new WasapiOut ();
output.Init (merged);
output.Play ();
Console.ReadKey ();
Good luck.

Unable to read QR using Zxing

I am using zxing library to generate and decode the QR codes. I my application I am generating QR code dynamically and sending the file containing QR by fax API. If I get this fax message from the api and decode it, Qr code is read successfully, but when I send a scanned copy of this file by fax and then receive and read it I am unable to do that. But if I try to read this file using my mobile Qr application it properly reads the Qr code. I am unable to find a solution how to read this file.
Methods used for encoding:
public static System.Drawing.Image GenerateJSONQrCode(QRJsonFax model)
{
var jsonString = JsonConvert.SerializeObject(model);
//encrypt json string
jsonString = Hugo.BLL.Utilities.EncryptionHelper.EncryptQR(jsonString, FaxSetting.IsUseHashing);
var bw = new ZXing.BarcodeWriter();
var encOptions = new ZXing.Common.EncodingOptions() { Width = 200, Height = 200, Margin = 0 };
bw.Options = encOptions;
bw.Format = ZXing.BarcodeFormat.QR_CODE;
var image = new Bitmap(bw.Write(Compress(jsonString)));
return image;
}
private static string Compress(string text)
{
byte[] buffer = Encoding.UTF8.GetBytes(text);
var ms = new MemoryStream();
using (var zip = new GZipStream(ms, CompressionMode.Compress, true))
{
zip.Write(buffer, 0, buffer.Length);
}
ms.Position = 0;
byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);
byte[] gzBuffer = new byte[compressed.Length + 4];
System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
return Convert.ToBase64String(gzBuffer);
}
Methods used for encoding and decoding
public static FaxReceiver.QrFinder DecodeQrCode(string imagePathToDecode)
{
long userId = 0;
Bitmap bitmapImage = (Bitmap)Image.FromFile(imagePathToDecode);
ZXing.BarcodeReader barcodeReader = new BarcodeReader() { AutoRotate = true, TryHarder = true }; ;
Result decode = barcodeReader.Decode(bitmapImage);
var scanResult = string.Empty;
if (decode != null)
{
scanResult= Decompress(decode.Text);
}
if (!string.IsNullOrWhiteSpace(scanResult))
{
//decrypt Qr received
var decryptedString = DecryptionHelper.Decrypt(scanResult, FaxSetting.IsUseHashing);
//deserialize JSON received
var resultJson = JsonConvert.DeserializeObject<QRJsonFax>(decryptedString);
if (resultJson != null)
{
long.TryParse(resultJson.UserID.ToString(), out userId);
return new QrFinder()
{
FilePath = imagePathToDecode,
UserId = userId,
PageNo = 0,
DataSourceID = resultJson.DataSourceID,
InboundFaxTypeID = resultJson.InboundFaxTypeID
};
}
}
return null;
}
private static string Decompress(string compressedText)
{
byte[] gzBuffer = Convert.FromBase64String(compressedText);
using (var ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
using (var zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Read(buffer, 0, buffer.Length);
}
return Encoding.UTF8.GetString(buffer);
}
}
File containing Qr code
The problem is that the QR Decoder is getting confused by the gaps between the pixels in your faxed image. If we zoom into a corner of it, this is what we see.
The scanner is looking for solid black squares to identify the QR code.
If we shrink the image by 50%, it becomes readable.
See for yourself at http://zxing.org/w/decode?u=http%3A%2F%2Fi.stack.imgur.com%2FSCYsd.png
I would suggest that after receiving the faxed image, you should either shrink it, or apply a filter to ensure that the QR codes are solid black. You could also look at sending it at a smaller resolution to see if that helps.

GZipStream decompress only 4kb of data

Why GZipStream, based on MemoryStream reads from it only 24576bytes and cant read any further? I compress my gz with multithreading, in parts, but winrar could decompress it and GZipStream not.
static private bool ZipperWork2(string InputPath, string OutputPath, CompressionMode CompMode)
{
Mode = CompMode;
RawData = new byte[ThreadCount][];
CompressedData = new byte[ThreadCount][];
Thread[] CompressorThreads = new Thread[ThreadCount];
byte[] buffer = new byte[MAX_BLOCK_SIZE];
using (FileStream fs = new FileStream(InputPath, FileMode.Open))
{
using (FileStream fw = new FileStream(OutputPath, FileMode.Append))
{
while (fs.Position < fs.Length)
{
for (int i = 0; i < ThreadCount; i++)
{
int count = fs.Read(buffer, 0, MAX_BLOCK_SIZE);
RawData[i] = new byte[count];
Array.Copy(buffer, RawData[i], count);
CompressorThreads[i] = new Thread(WorkWithBlock2);
CompressorThreads[i].Start(i);
}
for (int i = 0; i < ThreadCount; i++)
{
CompressorThreads[i].Join();
fw.Write(CompressedData[i], 0, CompressedData[i].Length);
}
}
}
}
return true;
}
private static void WorkWithBlock2(object index)
{
int DataIndex = (int)index;
//int count=0,totalcount=0;
using (MemoryStream ms = new MemoryStream(RawData[DataIndex]))
{
using (MemoryStream output = new MemoryStream())
{
using (GZipStream gz = new GZipStream(ms, Mode))
{
gz.CopyTo(output);
}
CompressedData[DataIndex] = output.ToArray();
}
}
}
I trying to do it in a different ways, but result are always the same, decompress only 4KB (and it don't relate with my MAX_BLOCK_SIZE variable)
Your gzip stream may actually consist of multiple concatenated gzip streams. This is permitted by the gzip format. GZipStream is likely just reading the first one. All you'd need to do is repeat the operation on the subsequent input bytes until all of the input bytes have been consumed.

AVIReader - taking too long to save frames

I am developing a program to grab images from four cameras and turn them into one picture only in style quad, 4 images in one. And it generate a .avi
AVIReader reader = new AVIReader();
List<byte[]> ImagemMainb = new List<byte[]>();
reader.Open(_rootPath + Path.GetFileName(_arqsCam01[i]));
while (reader.Position - reader.Start < reader.Length)
{
Bitmap aux = reader.GetNextFrame();
Bitmap r = new Bitmap(aux.Width * 2, aux.Height * 2, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
using (var g = Graphics.FromImage(r))
{
g.DrawImage(aux, new Rectangle(0, 0, aux.Width, aux.Height));
ImagemMainb.Add(ImageToByte(r));
}
}
reader.Close();
reader.Dispose();
And here is the method ImageToByte
public static byte[] ImageToByte(Image img)
{
byte[] byteArray = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Close();
byteArray = stream.ToArray();
}
return byteArray;
}
Using these codes takes too long to finish the process!
When I have a list of 84000 bitmaps in that case are 280 videos with frame rate = 5, size = 320x240, it takes forever.
Would have any problem in this code or have a better way?
i found the answer.
AVIReader reader = new AVIReader();
List<Bitmap> ImagemMain = new List<byte[]>();
reader.Open(_rootPath + Path.GetFileName(_arqs[0]));
while (reader.Position - reader.Start < reader.Length)
{
using (var aux = reader.GetNextFrame())
{
using (var r = new Bitmap(640, 480))
{
using (var g = Graphics.FromImage(r))
{
g.DrawImage(aux, new Rectangle(0, 0, aux.Width, aux.Height));
ImagemMain.Add((Bitmap)r.Clone());
}
}
}
}
Every video uploaded AVIWriter I open the file .avi and add bitmap.
With this is much more fast and does not take up almost no memory.

How to write NAudio WaveStream to a Memory Stream?

I have a program that takes in mp3 data in a byte array. It has to convert that mp3 data into wav format and store it in a byte data. I am trying to use NAudio for this purpose. I am using the following code for this purpose.
Stream inputStream = ...;
Stream outputStream = ...;
using (WaveStream waveStream = WaveFormatConversionStream.CreatePcmStream(new Mp3FileReader(inputStream)))
using (WaveFileWriter waveFileWriter = new WaveFileWriter(outputStream, waveStream.WaveFormat))
{
byte[] bytes = new byte[waveStream.Length];
waveStream.Read(bytes, 0, waveStream.Length);
waveFileWriter.WriteData(bytes, 0, bytes.Length);
waveFileWriter.Flush();
}
When I run the above code, all I receive is 0 in the byte array. But if use WaveFileWriter to write the data directly to a file, the file receives the correct data. Any reasons?
Give this a try:
using (WaveStream waveStream = WaveFormatConversionStream.CreatePcmStream(new Mp3FileReader(inputStream)))
using (WaveFileWriter waveFileWriter = new WaveFileWriter(outputStream, waveStream.WaveFormat))
{
byte[] bytes = new byte[waveStream.Length];
waveStream.Position = 0;
waveStream.Read(bytes, 0, waveStream.Length);
waveFileWriter.WriteData(bytes, 0, bytes.Length);
waveFileWriter.Flush();
}
If you are writing to a MemoryStream, you need to be aware that WaveFileWriter will dispose that MemoryStream after you dispose the WaveFileWriter.
Here's a workaround using the IgnoreDisposeStream. (Also note that WaveFormatConversionStream.CreatePcmStream is unnecessary - Mp3FileReader already returns PCM from Read). I also prefer to read in smaller chunks that trying to pass through the whole file.
var path = #"mytestFile.mp3";
var mp3ByteArray = File.ReadAllBytes(path);
var outputStream = new MemoryStream();
using (var mp3Stream = new MemoryStream(mp3ByteArray))
using (var reader = new Mp3FileReader(mp3Stream))
using (var waveFileWriter = new WaveFileWriter(new IgnoreDisposeStream(outputStream),
reader.WaveFormat))
{
byte[] buffer = new byte[reader.WaveFormat.AverageBytesPerSecond];
int read;
while((read = reader.Read(buffer,0, buffer.Length)) > 0)
{
waveFileWriter.Write(buffer, 0, read);
}
}
// outputStream has not yet been disposed so we can get the byte array from it
var wavBytes = outputStream.GetBuffer();
// or we could play it like this
outputStream.Position = 0;
using (var player = new WaveOutEvent())
using (var reader = new WaveFileReader(outputStream))
{
player.Init(reader);
player.Play();
while(player.PlaybackState != PlaybackState.Stopped)
{
Thread.Sleep(1000);
}
}

Categories

Resources