FileInputStream can not read file always - android-studio

I try to read a .raw audio file from the Android External Storage directory by using FileInputStream. Sometimes, I can read the file, sometimes not. What is the reason for this case?
Any help will be appreciated.
storageDir = Environment.getExternalStorageDirectory().getAbsolutePath();
enrollWavPath = storageDir + 1 + ".raw";
File file = new File(enrollRawPath);
byte[] byteData = null;
int size = (int) file.length();
byteData = new byte[(int)(size)];
FileInputStream iFileStream = new FileInputStream(file);
int bytesread = 0;
int ret = 0;
while (bytesread < size) {
ret = iFileStream.read( byteData,0, 2*count);
if (ret != -1) {
shortData = byte2short(byteData);
bytesread += ret;
}
else {
break;
}
}
iFileStream.close();

Related

NAudio Mp3 decoding click and pops

I followed this NAudio Demo modified to play ShoutCast.
In my full code I have to resample the incoming audio and stream it again over the network to a network player. Since I get many "clicks and pops", I came back to the demo code and I found that these artifacts are originated after the decoding block.
If I save the incoming stream in mp3 format, it is pretty clear.
When I save the raw decoded data (without other processing than the decoder) I get many audio artifacts.
I wonder whether I am doing some error, even if my code is almost equal to the NAudio demo.
Here the function from the example as modified by me to save the raw data. It is called as a new Thread.
private void StreamMP3(object state)
{
//Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//SettingsSection section = (SettingsSection)config.GetSection("system.net/settings");
this.fullyDownloaded = false;
string url = "http://icestreaming.rai.it/5.mp3";//(string)state;
webRequest = (HttpWebRequest)WebRequest.Create(url);
int metaInt = 0; // blocksize of mp3 data
int framesize = 0;
webRequest.Headers.Clear();
webRequest.Headers.Add("GET", "/ HTTP/1.0");
// needed to receive metadata informations
webRequest.Headers.Add("Icy-MetaData", "1");
webRequest.UserAgent = "WinampMPEG/5.09";
HttpWebResponse resp = null;
try
{
resp = (HttpWebResponse)webRequest.GetResponse();
}
catch (WebException e)
{
if (e.Status != WebExceptionStatus.RequestCanceled)
{
ShowError(e.Message);
}
return;
}
byte[] buffer = new byte[16384 * 4]; // needs to be big enough to hold a decompressed frame
try
{
// read blocksize to find metadata block
metaInt = Convert.ToInt32(resp.GetResponseHeader("icy-metaint"));
}
catch
{
}
IMp3FrameDecompressor decompressor = null;
byteOut = createNewFile(destPath, "salva", "raw");
try
{
using (var responseStream = resp.GetResponseStream())
{
var readFullyStream = new ReadFullyStream(responseStream);
readFullyStream.metaInt = metaInt;
do
{
if (mybufferedWaveProvider != null && mybufferedWaveProvider.BufferLength - mybufferedWaveProvider.BufferedBytes < mybufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4)
{
Debug.WriteLine("Buffer getting full, taking a break");
Thread.Sleep(500);
}
else
{
Mp3Frame frame = null;
try
{
frame = Mp3Frame.LoadFromStream(readFullyStream, true);
if (metaInt > 0)
UpdateSongName(readFullyStream.SongName);
else
UpdateSongName("No Song Info in Stream...");
}
catch (EndOfStreamException)
{
this.fullyDownloaded = true;
// reached the end of the MP3 file / stream
break;
}
catch (WebException)
{
// probably we have aborted download from the GUI thread
break;
}
if (decompressor == null)
{
// don't think these details matter too much - just help ACM select the right codec
// however, the buffered provider doesn't know what sample rate it is working at
// until we have a frame
WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate);
decompressor = new AcmMp3FrameDecompressor(waveFormat);
this.mybufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat);
this.mybufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(200); // allow us to get well ahead of ourselves
framesize = (decompressor.OutputFormat.Channels * decompressor.OutputFormat.SampleRate * (decompressor.OutputFormat.BitsPerSample / 8) * 20) / 1000;
//this.bufferedWaveProvider.BufferedDuration = 250;
}
int decompressed = decompressor.DecompressFrame(frame, buffer, 0);
//Debug.WriteLine(String.Format("Decompressed a frame {0}", decompressed));
mybufferedWaveProvider.AddSamples(buffer, 0, decompressed);
while (mybufferedWaveProvider.BufferedDuration.Milliseconds >= 20)
{
byte[] read = new byte[framesize];
mybufferedWaveProvider.Read(read, 0, framesize);
byteOut.Write(read, 0, framesize);
}
}
} while (playbackState != StreamingPlaybackState.Stopped);
Debug.WriteLine("Exiting");
// was doing this in a finally block, but for some reason
// we are hanging on response stream .Dispose so never get there
decompressor.Dispose();
}
}
finally
{
if (decompressor != null)
{
decompressor.Dispose();
}
}
}
OK i found the problem. I included the shoutcast metadata to the MP3Frame.
See the comment "HERE I COLLECT THE BYTES OF THE MP3 FRAME" to locate the correct point to get the MP3 frame with no streaming metadata.
The following code runs without audio artifacts:
private void SHOUTcastReceiverThread()
{
//-*- String server = "http://216.235.80.18:8285/stream";
//String serverPath = "/";
//String destPath = "C:\\temp\\"; // destination path for saved songs
HttpWebRequest request = null; // web request
HttpWebResponse response = null; // web response
int metaInt = 0; // blocksize of mp3 data
int count = 0; // byte counter
int metadataLength = 0; // length of metadata header
string metadataHeader = ""; // metadata header that contains the actual songtitle
string oldMetadataHeader = null; // previous metadata header, to compare with new header and find next song
//CircularQueueStream framestream = new CircularQueueStream(2048);
QueueStream framestream = new QueueStream();
framestream.Position = 0;
bool bNewSong = false;
byte[] buffer = new byte[512]; // receive buffer
byte[] dec_buffer = new byte[decSIZE];
Mp3Frame frame;
IMp3FrameDecompressor decompressor = null;
Stream socketStream = null; // input stream on the web request
// create web request
request = (HttpWebRequest)WebRequest.Create(server);
// clear old request header and build own header to receive ICY-metadata
request.Headers.Clear();
request.Headers.Add("GET", serverPath + " HTTP/1.0");
request.Headers.Add("Icy-MetaData", "1"); // needed to receive metadata informations
request.UserAgent = "WinampMPEG/5.09";
// execute request
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
// read blocksize to find metadata header
metaInt = Convert.ToInt32(response.GetResponseHeader("icy-metaint"));
try
{
// open stream on response
socketStream = response.GetResponseStream();
var readFullyStream = new ReadFullyStream(socketStream);
frame = null;
// rip stream in an endless loop
do
{
if (IsBufferNearlyFull)
{
Debug.WriteLine("Buffer getting full, taking a break");
Thread.Sleep(500);
frame = null;
}
else
{
int bufLen = readFullyStream.Read(buffer, 0, buffer.Length);
try
{
if (framestream.CanRead && framestream.Length > 512)
frame = Mp3Frame.LoadFromStream(framestream);
else
frame = null;
}
catch (Exception ex)
{
frame = null;
}
if (bufLen < 0)
{
Debug.WriteLine("Buffer error 1: exit.");
return;
}
// processing RAW data
for (int i = 0; i < bufLen; i++)
{
// if there is a header, the 'headerLength' would be set to a value != 0. Then we save the header to a string
if (metadataLength != 0)
{
metadataHeader += Convert.ToChar(buffer[i]);
metadataLength--;
if (metadataLength == 0) // all metadata informations were written to the 'metadataHeader' string
{
string fileName = "";
string fileNameRaw = "";
// if songtitle changes, create a new file
if (!metadataHeader.Equals(oldMetadataHeader))
{
// flush and close old byteOut stream
if (byteOut != null)
{
byteOut.Flush();
byteOut.Close();
byteOut = null;
}
if (byteOutRaw != null)
{
byteOutRaw.Flush();
byteOutRaw.Close();
byteOutRaw = null;
}
timeStart = timeEnd;
// extract songtitle from metadata header. Trim was needed, because some stations don't trim the songtitle
//fileName = Regex.Match(metadataHeader, "(StreamTitle=')(.*)(';StreamUrl)").Groups[2].Value.Trim();
fileName = Regex.Match(metadataHeader, "(StreamTitle=')(.*)(';)").Groups[2].Value.Trim();
// write new songtitle to console for information
if (fileName.Length == 0)
fileName = "shoutcast_test";
fileNameRaw = fileName + "_raw";
framestream.reSetPosition();
SongChanged(this, metadataHeader);
bNewSong = true;
// create new file with the songtitle from header and set a stream on this file
timeEnd = DateTime.Now;
if (bWrite_to_file)
{
byteOut = createNewFile(destPath, fileName, "mp3");
byteOutRaw = createNewFile(destPath, fileNameRaw, "raw");
}
timediff = timeEnd - timeStart;
// save new header to 'oldMetadataHeader' string, to compare if there's a new song starting
oldMetadataHeader = metadataHeader;
}
metadataHeader = "";
}
}
else // write mp3 data to file or extract metadata headerlength
{
if (count++ < metaInt) // write bytes to filestream
{
//HERE I COLLECT THE BYTES OF THE MP3 FRAME
framestream.Write(buffer, i, 1);
}
else // get headerlength from lengthbyte and multiply by 16 to get correct headerlength
{
metadataLength = Convert.ToInt32(buffer[i]) * 16;
count = 0;
}
}
}//for
if (bNewSong)
{
decompressor = createDecompressor(frame);
bNewSong = false;
}
if (frame != null && decompressor != null)
{
framedec(decompressor, frame);
}
// fine Processing dati RAW
}//Buffer is not full
SHOUTcastStatusProcess();
} while (playbackState != StreamingPlaybackState.Stopped);
} //try
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (byteOut != null)
byteOut.Close();
if (socketStream != null)
socketStream.Close();
if (decompressor != null)
{
decompressor.Dispose();
decompressor = null;
}
if (null != request)
request.Abort();
if (null != framestream)
framestream.Dispose();
if (null != bufferedWaveProvider)
bufferedWaveProvider.ClearBuffer();
//if (null != bufferedWaveProviderOut)
// bufferedWaveProviderOut.ClearBuffer();
if (null != mono16bitFsinStream)
{
mono16bitFsinStream.Close();
mono16bitFsinStream.Dispose();
}
if (null != middleStream2)
{
middleStream2.Close();
middleStream2.Dispose();
}
if (null != resampler)
resampler.Dispose();
}
}
public class QueueStream : MemoryStream
{
long ReadPosition = 0;
long WritePosition = 0;
public QueueStream() : base() { }
public override int Read(byte[] buffer, int offset, int count)
{
Position = ReadPosition;
var temp = base.Read(buffer, offset, count);
ReadPosition = Position;
return temp;
}
public override void Write(byte[] buffer, int offset, int count)
{
Position = WritePosition;
base.Write(buffer, offset, count);
WritePosition = Position;
}
public void reSetPosition()
{
WritePosition = 0;
ReadPosition = 0;
Position = 0;
}
}
private void framedec(IMp3FrameDecompressor decompressor, Mp3Frame frame)
{
int Ndecoded_samples = 0;
byte[] dec_buffer = new byte[decSIZE];
Ndecoded_samples = decompressor.DecompressFrame(frame, dec_buffer, 0);
bufferedWaveProvider.AddSamples(dec_buffer, 0, Ndecoded_samples);
NBufferedSamples += Ndecoded_samples;
brcnt_in.incSamples(Ndecoded_samples);
if (Ndecoded_samples > decSIZE)
{
Debug.WriteLine(String.Format("Too many samples {0}", Ndecoded_samples));
}
if (byteOut != null)
byteOut.Write(frame.RawData, 0, frame.RawData.Length);
if (byteOutRaw != null) // as long as we don't have a songtitle, we don't open a new file and don't write any bytes
byteOutRaw.Write(dec_buffer, 0, Ndecoded_samples);
frame = null;
}
private IMp3FrameDecompressor createDecompressor(Mp3Frame frame)
{
IMp3FrameDecompressor dec = null;
if (frame != null)
{
// don't think these details matter too much - just help ACM select the right codec
// however, the buffered provider doesn't know what sample rate it is working at
// until we have a frame
WaveFormat srcwaveFormat = new Mp3WaveFormat(frame.SampleRate, frame.ChannelMode == ChannelMode.Mono ? 1 : 2, frame.FrameLength, frame.BitRate);
dec = new AcmMp3FrameDecompressor(srcwaveFormat);
bufferedWaveProvider = new BufferedWaveProvider(dec.OutputFormat);// decompressor.OutputFormat
bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(400); // allow us to get well ahead of ourselves
// ------------------------------------------------
//Create an intermediate format with same sampling rate, 16 bit, mono
middlewavformat = new WaveFormat(dec.OutputFormat.SampleRate, 16, 1);
outwavFormat = new WaveFormat(Fs_out, 16, 1);
// wave16ToFloat = new Wave16ToFloatProvider(provider); // I have tried with and without this converter.
wpws = new WaveProviderToWaveStream(bufferedWaveProvider);
//Check middlewavformat.Encoding == WaveFormatEncoding.Pcm;
mono16bitFsinStream = new WaveFormatConversionStream(middlewavformat, wpws);
middleStream2 = new BlockAlignReductionStream(mono16bitFsinStream);
resampler = new MediaFoundationResampler(middleStream2, outwavFormat);
}
return dec;
}

NAudio WaveBadFormat exception while trying to streaming mp3

I am trying to play an mp3 from an internet source while streaming in the same time. I've writen the code below and it throws the exception WaveBadFormat calling WaveOut at the player.Init() line. How should I fix this?
string testLink = "http://users.skynet.be/fa046054/home/P22/track49.mp3";
req = WebRequest.Create(testLink) as HttpWebRequest;
resp = req.GetResponse() as HttpWebResponse;
str = resp.GetResponseStream();
int readBytes = 0;
int totalBytes = 0;
byte[] buffer = new byte[1024];
byte[] mp3Buffer = new byte[45000];
IMp3FrameDecompressor decompressor = null;
BufferedWaveProvider provider = null;
WaveOut player = new WaveOut();
Mp3Frame frame = Mp3Frame.LoadFromStream(new ReadFullyStream(str));
while ((readBytes = str.Read(buffer, 0, buffer.Length)) > 0)
{
totalBytes += readBytes;
if (decompressor == null && totalBytes > 1024)
{
Mp3WaveFormat format = new Mp3WaveFormat(frame.SampleRate,
frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
frame.FrameLength, frame.BitRate);
decompressor = new AcmMp3FrameDecompressor(format);
provider = new BufferedWaveProvider(format);
int x = decompressor.DecompressFrame(frame, mp3Buffer, 0);
provider.AddSamples(mp3Buffer, 0, x);
player.Init(provider);
player.Play();
continue;
}
Application.DoEvents();
if (decompressor == null)
continue;
int decNum = decompressor.DecompressFrame(frame, mp3Buffer, 0);
provider.AddSamples(mp3Buffer, 0, decNum);
}
the WaveFormat of your BufferedWaveProvider should be the PCM format you decompress the MP3 into, not an Mp3WaveFormat. Your WaveOut device can only play PCM.

why large file is corrupting sometimes while uploading it to Azure blob

I am uploading a large file in azure storage . I am uploading a file in to 4 MB chunks. I used the following code from last 1 year but from last one month whenever I am uploading file It is getting corrupt some times and some times It uploads fine.
Can any one suggest me what I need to change in the code.
//Uploads a file from the file system to a blob. Parallel implementation.
public void ParallelUploadFile(CloudBlockBlob blob1, string fileName1, BlobRequestOptions options1, int maxBlockSize = 4 * 1024 * 1024, int rowId)
{
blob = blob1;
fileName = fileName1;
options = options1;
file = new FileInfo(fileName);
var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read,FileShare.ReadWrite);
long fileSize = file.Length;
//Get the filesize
long fileSizeInMb = file.Length/1024/1024;
// let's figure out how big the file is here
long leftToRead = fileSize;
long startPosition = 0;
// have 1 block for every maxBlockSize bytes plus 1 for the remainder
var blockCount =
((int) Math.Floor((double) (fileSize/maxBlockSize))) + 1;
blockIds = new List<string>();
// populate the control array...
for (int j = 0; j < blockCount; j++)
{
var toRead = (int) (maxBlockSize < leftToRead
? maxBlockSize
: leftToRead);
var blockId = Convert.ToBase64String(
Encoding.ASCII.GetBytes(
string.Format("BlockId{0}", j.ToString("0000000"))));
transferDetails.Add(new BlockTransferDetail()
{
StartPosition = startPosition,
BytesToRead = toRead,
BlockId = blockId
});
if (toRead > 0)
{
blockIds.Add(blockId);
}
// increment the starting position
startPosition += toRead;
leftToRead -= toRead;
}
//*******
//PUT THE NO OF THREAD LOGIC HERE
//*******
int runFrom = 0;
int runTo = 0;
int uploadParametersCount = 0;
TotalUpload = Convert.ToInt64(fileSizeInMb);
for (int count = 0; count < transferDetails.Count; )
{
//Create uploading file parameters
uploadParametersesList.Add(new UploadParameters()
{
FileName = file.FullName,
BlockSize = 3900000,
//BlockSize = 4194304,
LoopFrom = runFrom + runTo,
IsPutBlockList = false,
UploadedBytes = 0,
Fs = fileStream,
RowIndex = rowId,
FileSize = Convert.ToInt64(fileSizeInMb)
});
//Logic to create correct threads
if (transferDetails.Count < 50)
{
runTo = transferDetails.Count;
uploadParametersesList[uploadParametersCount].LoopTo += runTo;
count += transferDetails.Count;
}
else
{
var tmp = transferDetails.Count - runTo;
if (tmp > 50 && tmp < 100)
{
runTo += tmp;
count += tmp;
uploadParametersesList[uploadParametersCount].LoopTo += runTo;
}
else
{
runTo += 50;
count += 50;
uploadParametersesList[uploadParametersCount].LoopTo += runTo;
}
}
//Add to Global Const
GlobalConst.UploadedParameters.Add(uploadParametersesList[uploadParametersCount]);
//Start the thread
int parametersCount = uploadParametersCount;
var thread = new Thread(() => ThRunThis(uploadParametersesList[parametersCount]))
{Priority = ThreadPriority.Highest};
thread.Start();
uploadParametersCount++;
//Start a timer here to put all blocks on azure blob
aTimer.Elapsed += OnTimedEvent;
aTimer.Interval = 5000;
aTimer.Start();
}
}
//Timer callback
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
if (uploadParametersesList.Count(o => o.IsPutBlockList) == uploadParametersesList.Count)
{
aTimer.Elapsed -= OnTimedEvent;
aTimer.Stop();
//Finally commit it
try
{
uploadParametersesList.ForEach(x => x.Status = "Uploaded");
blob.PutBlockList(blockIds);
IsCompleted = true;
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
}
//Main thread
private void ThRunThis(UploadParameters uploadParameters)
{
try
{
for (int j = uploadParameters.LoopFrom; j < uploadParameters.LoopTo; j++)
{
br = new BinaryReader(uploadParameters.Fs);
var bytes = new byte[transferDetails[j].BytesToRead];
//move the file system reader to the proper position
uploadParameters.Fs.Seek(transferDetails[j].StartPosition, SeekOrigin.Begin);
br.Read(bytes, 0, transferDetails[j].BytesToRead);
if (bytes.Length > 0)
{
//calculate the block-level hash
MD5 md5 = new MD5CryptoServiceProvider();
byte[] blockHash = md5.ComputeHash(bytes);
string convertedHash = Convert.ToBase64String(blockHash, 0, 16);
blob.PutBlock(transferDetails[j].BlockId, new MemoryStream(bytes), convertedHash, options);
//Update Uploaded Bytes
uploadParameters.UploadedBytes += transferDetails[j].BytesToRead;
TotalUploadedBytes += transferDetails[j].BytesToRead;
Console.WriteLine(Thread.CurrentThread.Name);
//Try to free the memory
try
{
GC.Collect();
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
}
//Is Completed
uploadParameters.IsPutBlockList = true;
}
catch (Exception exception)
{
Console.WriteLine(Thread.CurrentThread.Name);
uploadParameters.Exception = exception.Message;
Console.WriteLine(exception.Message);
}
}
It's been a long time since I touched large blob upload with threads, but it looks like your block list is getting out of sequence by threads.
Why don't you get the block list from cloud once all blocks have been uploaded and then use that list for putBlockList. That would make sure you get them in correct sequence.

J2ME nokia s40 out of memory exception

I am trying to read a 2mb file into a memory and then send that file to web server. But I am getting out of memory exception.
FileConnection fileConn = (FileConnection)Connector.open("file:///" + pictureURI.getString(), Connector.READ);
InputStream fis = fileConn.openInputStream();
long overallSize = fileConn.fileSize();
int chunkSize = 2048;
int length = 0;
while (length < overallSize)
{
byte[] data = new byte[chunkSize];
int readAmount = fis.read(data, 0, chunkSize);
byte[] newImageData = new byte[rawImage.length + chunkSize];
System.arraycopy(rawImage, 0, newImageData, 0, length);
System.arraycopy(data, 0, newImageData, length, readAmount);
rawImage = newImageData;
length += readAmount;
}
fis.close();
fileConn.close();
500kb files are uploading. What could be the reason? Please shed a light on this.
I tried this also in loop but no use, System.gc();
[EDIT]
https://stackoverflow.com/users/45668/malcolm has put me on right track. Now I struck here
this.progress = progress;
HttpConnection conn = null;
OutputStream os = null;
InputStream s = null;
StringBuffer responseString = new StringBuffer();
try
{
System.out.println(System.getProperty("HTTPClient.dontChunkRequests"));
conn = (HttpConnection)Connector.open(url);
//conn.setRequestProperty("User-Agent", "Profile/MIDP-2.1 Configuration/CLDC-1.1");
conn.setRequestMethod(HttpConnection.POST);
// The messages
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=---------------------------4664151417711");
conn.setRequestProperty("Content-Length", "355");
os = conn.openOutputStream();
System.out.println("file name at upload " + fileName);
String message1 = "";
message1 += "-----------------------------4664151417711\r\n";
message1 += "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n";
message1 += "Content-Type: image/gif\r\n";
message1 += "\r\n";
os.write(message1.getBytes());
System.gc();
// Send the image
int index = 0;
int size = 2048;
double progdouble;
do
{
progdouble = ((double)index) / ((double)rawImage.length) * 100;
progress.setValue((int)progdouble);
if((index+size) > rawImage.length)
{
size = rawImage.length - index;
}
os.write(rawImage, index, size);
index += size;
System.gc();
} while(index < rawImage.length);
String message2 = "\r\n-----------------------------4664151417711\r\n";
message2 += "Content-Disposition: form-data; name=\"number\"\r\n\r\n";
message2 += this.user_phone_number;
os.write(message2.getBytes());
String message3 = "\r\n-----------------------------4664151417711\r\n";
message3 += "Content-Disposition: form-data; name=\"uuid\"\r\n\r\n";
message3 += this.user_uuid;
os.write(message3.getBytes());
String message4 = "\r\n-----------------------------4664151417711--\r\n";
os.write(message4.getBytes());
os.flush();
os.close();
// Read
s = conn.openInputStream();
int ch, i = 0, maxSize = 16384;
while(((ch = s.read())!= -1 ) & (i++ < maxSize))
{
responseString.append((char) ch);
}
conn.close();
System.out.println("response =>"+responseString.toString());
return responseString.toString();
}
catch (IOException ioe)
{
return ioe.toString();
}
Now its failing here..
[EDIT2]
// algorithm that will read 1024 bytes at a time
byte b[] = new byte[chunkSize];
for (int i = 0; i < overallSize; i += chunkSize) {
if ((i + chunkSize) < overallSize) {
fis.read(b, 0, chunkSize);
} else {
int left = (int)overallSize - i;
fis.read(b, 0, left);
}
// writing into the output stream - ( these lines will cause the "memory leak", without these, it will not happen)
os.write(b);
System.gc();
progdouble = ((double)i) / ((double)overallSize) * 100;
progress.setValue((int)progdouble);
}
os.flush();
Thanks in advance.
You allocate a lot of new arrays along the way, which is totally unnecessary. Each new byte[] line allocates a new array.
You should read into one large array, and you should allocate it once, before the loop. You can easily do this since you know the exact size of the file. The code will look something like this:
FileConnection fileConn;
InputStream is;
try {
fileConn = (FileConnection) Connector.open("file:///" + pictureURI.getString(), Connector.READ);
is = fileConn.openInputStream();
long overallSize = fileConn.fileSize();
if (overallSize > Integer.MAX_VALUE) throw new IllegalArgumentException("File is too large);
byte[] imageData = new byte[(int) overallSize];
int chunkSize = 2048;
int bytesReadTotal = 0;
while (bytesRead < overallSize) {
int bytesRead = is.read(imageData, bytesReadTotal, Math.min(imageData.length - bytesReadTotal, chunkSize));
if (bytesRead == -1) break;
bytesReadTotal += bytesRead;
}
} finally {
if (is != null) is.close();
if (fileConn != null) fileConn.close();
}
Your mobile (Nokia x2-01 specs) is limited to 2Mb of heap space for the whole app. Design your app according to these limitations. 2Mb bytearray in memory at once - no way.

Silverlight Speex playing at fast rate

I'm using Speex to encode the raw data but after I decode the data the audio plays at a faster rate because it makes you sound like a chipmunk. I'm using NSpeex and Silverlight 4.
8kHz Sampling
Encoding Function:
JSpeexEnc encoder = new JSpeexEnc();
int rawDataSize = 0;
public byte[] EncodeAudio(byte[] rawData)
{
var encoder = new SpeexEncoder(BandMode.Narrow);
var inDataSize = rawData.Length / 2;
var inData = new short[inDataSize];
for (var index = 0; index < rawData.Length; index += 2)
{
inData[index / 2] = BitConverter.ToInt16(rawData, index);
}
inDataSize = inDataSize - inDataSize % encoder.FrameSize;
var encodedData = new byte[rawData.Length];
var encodedBytes = encoder.Encode(inData, 0, inDataSize, encodedData, 0, encodedData.Length);
byte[] encodedAudioData = null;
if (encodedBytes != 0)
{
encodedAudioData = new byte[encodedBytes];
Array.Copy(encodedData, 0, encodedAudioData, 0, encodedBytes);
}
rawDataSize = inDataSize; // Count of encoded shorts, for debugging
return encodedAudioData;
}
Decoding Function:
SpeexDecoder decoder = new SpeexDecoder(BandMode.Narrow);
public byte[] Decode(byte[] encodedData)
{
try
{
short[] decodedFrame = new short[8000]; // should be the same number of samples as on the capturing side
int decoderBytes = decoder.Decode(encodedData, 0, encodedData.Length, decodedFrame, 0, false);
byte[] decodedData = new byte[encodedData.Length];
byte[] decodedAudioData = null;
decodedAudioData = new byte[decoderBytes * 2];
for (int shortIndex = 0, byteIndex = 0; byteIndex < decoderBytes; shortIndex++)
{
BitConverter.GetBytes(decodedFrame[shortIndex + byteIndex]).CopyTo(decodedAudioData, byteIndex * 2);
byteIndex++;
}
// todo: do something with the decoded data
return decodedAudioData;
}
catch (Exception ex)
{
ShowMessageBox(ex.Message.ToString());
return null;
}
}
Playing the audio:
void PlayWave(byte[] PCMBytes)
{
byte[] decodedBuffer = Decode(PCMBytes);
MemoryStream ms_PCM = new MemoryStream(decodedBuffer);
MemoryStream ms_Wave = new MemoryStream();
_pcm.SavePcmToWav(ms_PCM, ms_Wave, 16, 8000, 1);
WaveMediaStreamSource WaveStream = new WaveMediaStreamSource(ms_Wave);
mediaElement1.SetSource(WaveStream);
mediaElement1.Play();
}
Sorry guys for the late response but I figured out what the problem was.
Inside my decode function I loop through the decoded short array but I'm only copying half of the bytes into my new byte array.
It needs to look something like this:
decodedAudioData = new byte[decoderBytes * 2];
for (int shortIndex = 0, byteIndex = 0; shortIndex < decodedFrame.Length; shortIndex++, byteIndex += 2)
{
byte[] temp = BitConverter.GetBytes(decodedFrame[shortIndex]);
decodedAudioData[byteIndex] = temp[0];
decodedAudioData[byteIndex + 1] = temp[1];
}

Resources