Skip to content
This repository has been archived by the owner on Apr 18, 2019. It is now read-only.

Commit

Permalink
Merge pull request #23 from sgrebnov/master
Browse files Browse the repository at this point in the history
licensing issues/improvements
  • Loading branch information
purplecabbage committed Oct 31, 2012
2 parents c7e56d7 + 3ea1b5d commit 0257b98
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 193 deletions.
89 changes: 89 additions & 0 deletions framework/CordovaLib/Commands/AudioFormatsHelper.cs
@@ -0,0 +1,89 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

using System;
using System.IO;

namespace WP7CordovaClassLib.Cordova.Commands
{
/// <summary>
/// Provides extra functionality to support different audio formats.
/// </summary>
public static class AudioFormatsHelper
{
#region Wav
/// <summary>
/// Adds wav file format header to the stream
/// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
/// </summary>
/// <param name="stream">The stream</param>
/// <param name="sampleRate">Sample Rate</param>
public static void InitializeWavStream(this Stream stream, int sampleRate)
{
#region args checking

if (stream == null)
{
throw new ArgumentNullException("stream can't be null or empty");
}

#endregion

int numBits = 16;
int numBytes = numBits / 8;

stream.Write(System.Text.Encoding.UTF8.GetBytes("RIFF"), 0, 4);
stream.Write(BitConverter.GetBytes(0), 0, 4);
stream.Write(System.Text.Encoding.UTF8.GetBytes("WAVE"), 0, 4);
stream.Write(System.Text.Encoding.UTF8.GetBytes("fmt "), 0, 4);
stream.Write(BitConverter.GetBytes(16), 0, 4);
stream.Write(BitConverter.GetBytes((short)1), 0, 2);
stream.Write(BitConverter.GetBytes((short)1), 0, 2);
stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);
stream.Write(BitConverter.GetBytes(sampleRate * numBytes), 0, 4);
stream.Write(BitConverter.GetBytes((short)(numBytes)), 0, 2);
stream.Write(BitConverter.GetBytes((short)(numBits)), 0, 2);
stream.Write(System.Text.Encoding.UTF8.GetBytes("data"), 0, 4);
stream.Write(BitConverter.GetBytes(0), 0, 4);
}

/// <summary>
/// Updates wav file format header
/// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
/// </summary>
/// <param name="stream">Wav stream</param>
public static void UpdateWavStream(this Stream stream)
{
#region args checking

if (stream == null)
{
throw new ArgumentNullException("stream can't be null or empty");
}

#endregion

var position = stream.Position;

stream.Seek(4, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4);
stream.Seek(40, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4);
stream.Seek(position, SeekOrigin.Begin);
}

#endregion
}
}
1 change: 1 addition & 0 deletions framework/WP7CordovaClassLib.csproj
Expand Up @@ -184,6 +184,7 @@
<Link>CordovaLib\UI\VideoRecorder.xaml.cs</Link>
<DependentUpon>VideoRecorder.xaml</DependentUpon>
</Compile>
<Compile Include="CordovaLib\Commands\AudioFormatsHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
87 changes: 3 additions & 84 deletions templates/standalone/cordovalib/Commands/AudioPlayer.cs
Expand Up @@ -168,7 +168,7 @@ public void startRecording(string filePath)
this.buffer = new byte[recorder.GetSampleSizeInBytes(this.recorder.BufferDuration)];
this.recorder.BufferReady += new EventHandler<EventArgs>(recorderBufferReady);
this.memoryStream = new MemoryStream();
this.WriteWavHeader(this.memoryStream, this.recorder.SampleRate);
this.memoryStream.InitializeWavStream(this.recorder.SampleRate);
this.recorder.Start();
FrameworkDispatcher.Update();
this.SetState(PlayerState_Running);
Expand Down Expand Up @@ -495,7 +495,7 @@ private void SaveAudioClipToLocalStorage()
return;
}

this.UpdateWavHeader(this.memoryStream);
this.memoryStream.UpdateWavStream();

try
{
Expand All @@ -521,88 +521,7 @@ private void SaveAudioClipToLocalStorage()
//TODO: log or do something else
throw;
}
}



#region Wav format
// Original source http://damianblog.com/2011/02/07/storing-wp7-recorded-audio-as-wav-format-streams/

/// <summary>
/// Adds wav file format header to the stream
/// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
/// </summary>
/// <param name="stream">Wav stream</param>
/// <param name="sampleRate">Sample Rate</param>
private void WriteWavHeader(Stream stream, int sampleRate)
{
const int bitsPerSample = 16;
const int bytesPerSample = bitsPerSample / 8;
var encoding = System.Text.Encoding.UTF8;

// ChunkID Contains the letters "RIFF" in ASCII form (0x52494646 big-endian form).
stream.Write(encoding.GetBytes("RIFF"), 0, 4);

// NOTE this will be filled in later
stream.Write(BitConverter.GetBytes(0), 0, 4);

// Format Contains the letters "WAVE"(0x57415645 big-endian form).
stream.Write(encoding.GetBytes("WAVE"), 0, 4);

// Subchunk1ID Contains the letters "fmt " (0x666d7420 big-endian form).
stream.Write(encoding.GetBytes("fmt "), 0, 4);

// Subchunk1Size 16 for PCM. This is the size of therest of the Subchunk which follows this number.
stream.Write(BitConverter.GetBytes(16), 0, 4);

// AudioFormat PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
stream.Write(BitConverter.GetBytes((short)1), 0, 2);

// NumChannels Mono = 1, Stereo = 2, etc.
stream.Write(BitConverter.GetBytes((short)1), 0, 2);

// SampleRate 8000, 44100, etc.
stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);

// ByteRate = SampleRate * NumChannels * BitsPerSample/8
stream.Write(BitConverter.GetBytes(sampleRate * bytesPerSample), 0, 4);

// BlockAlign NumChannels * BitsPerSample/8 The number of bytes for one sample including all channels.
stream.Write(BitConverter.GetBytes((short)(bytesPerSample)), 0, 2);

// BitsPerSample 8 bits = 8, 16 bits = 16, etc.
stream.Write(BitConverter.GetBytes((short)(bitsPerSample)), 0, 2);

// Subchunk2ID Contains the letters "data" (0x64617461 big-endian form).
stream.Write(encoding.GetBytes("data"), 0, 4);

// NOTE to be filled in later
stream.Write(BitConverter.GetBytes(0), 0, 4);
}

/// <summary>
/// Updates wav file format header
/// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
/// </summary>
/// <param name="stream">Wav stream</param>
private void UpdateWavHeader(Stream stream)
{
if (!stream.CanSeek) throw new Exception("Can't seek stream to update wav header");

var oldPos = stream.Position;

// ChunkSize 36 + SubChunk2Size
stream.Seek(4, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4);

// Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8 This is the number of bytes in the data.
stream.Seek(40, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4);

stream.Seek(oldPos, SeekOrigin.Begin);
}

#endregion
}

#region Xna loop
/// <summary>
Expand Down
17 changes: 2 additions & 15 deletions templates/standalone/cordovalib/Commands/ImageExifHelper.cs
Expand Up @@ -10,26 +10,13 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*
* Portions of this code are based on Simon McKenzie's ExifLib
* http://www.codeproject.com/Articles/36342/ExifLib-A-Fast-Exif-Data-Extractor-for-NET-2-0
*/



using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.IO;
using System.Windows.Media.Imaging;
using System.Diagnostics;

namespace WP7CordovaClassLib.Cordova.Commands
{
Expand Down
8 changes: 1 addition & 7 deletions templates/standalone/cordovalib/Commands/Notification.cs
Expand Up @@ -47,14 +47,8 @@ private PhoneApplicationPage Page
}
}

// alert, confirm, blink, vibrate, beep
// blink api - doesn't look like there is an equivalent api we can use...
// vibrate api - http://msdn.microsoft.com/en-us/library/microsoft.devices.vibratecontroller(v=VS.92).aspx
// beep api - can probably use: http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.alarm(v=VS.92).aspx
// - examples of alarm class http://mkdot.net/blogs/filip/archive/2011/06/06/windows-phone-multitasking-part-2-2.aspx

//MessageBoxResult res = MessageBox.Show("Could not call script: " + ex.Message, "caption", MessageBoxButton.OKCancel);


[DataContract]
public class AlertOptions
{
Expand Down
94 changes: 7 additions & 87 deletions templates/standalone/cordovalib/UI/AudioRecorder.xaml.cs
Expand Up @@ -12,15 +12,16 @@
limitations under the License.
*/

using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using WP7CordovaClassLib.Cordova.Commands;
using AudioResult = WP7CordovaClassLib.Cordova.UI.AudioCaptureTask.AudioResult;

namespace WP7CordovaClassLib.Cordova.UI
Expand Down Expand Up @@ -122,7 +123,7 @@ private void StartRecording()
this.microphone.BufferReady += new EventHandler<EventArgs>(MicrophoneBufferReady);

this.memoryStream = new MemoryStream();
this.WriteWavHeader(this.memoryStream, this.microphone.SampleRate);
this.memoryStream.InitializeWavStream(this.microphone.SampleRate);

this.duration = new TimeSpan(0);

Expand Down Expand Up @@ -233,7 +234,7 @@ private AudioResult SaveAudioClipToLocalStorage()
return new AudioResult(TaskResult.Cancel);
}

this.UpdateWavHeader(this.memoryStream);
this.memoryStream.UpdateWavStream();

// save audio data to local isolated storage

Expand Down Expand Up @@ -302,86 +303,5 @@ private void FinalizeXnaGameLoop()
}
}


#region Wav format
// Original source http://damianblog.com/2011/02/07/storing-wp7-recorded-audio-as-wav-format-streams/

/// <summary>
/// Adds wav file format header to the stream
/// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
/// </summary>
/// <param name="stream">Wav stream</param>
/// <param name="sampleRate">Sample Rate</param>
private void WriteWavHeader(Stream stream, int sampleRate)
{
const int bitsPerSample = 16;
const int bytesPerSample = bitsPerSample / 8;
var encoding = System.Text.Encoding.UTF8;

// ChunkID Contains the letters "RIFF" in ASCII form (0x52494646 big-endian form).
stream.Write(encoding.GetBytes("RIFF"), 0, 4);

// NOTE this will be filled in later
stream.Write(BitConverter.GetBytes(0), 0, 4);

// Format Contains the letters "WAVE"(0x57415645 big-endian form).
stream.Write(encoding.GetBytes("WAVE"), 0, 4);

// Subchunk1ID Contains the letters "fmt " (0x666d7420 big-endian form).
stream.Write(encoding.GetBytes("fmt "), 0, 4);

// Subchunk1Size 16 for PCM. This is the size of therest of the Subchunk which follows this number.
stream.Write(BitConverter.GetBytes(16), 0, 4);

// AudioFormat PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
stream.Write(BitConverter.GetBytes((short)1), 0, 2);

// NumChannels Mono = 1, Stereo = 2, etc.
stream.Write(BitConverter.GetBytes((short)1), 0, 2);

// SampleRate 8000, 44100, etc.
stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);

// ByteRate = SampleRate * NumChannels * BitsPerSample/8
stream.Write(BitConverter.GetBytes(sampleRate * bytesPerSample), 0, 4);

// BlockAlign NumChannels * BitsPerSample/8 The number of bytes for one sample including all channels.
stream.Write(BitConverter.GetBytes((short)(bytesPerSample)), 0, 2);

// BitsPerSample 8 bits = 8, 16 bits = 16, etc.
stream.Write(BitConverter.GetBytes((short)(bitsPerSample)), 0, 2);

// Subchunk2ID Contains the letters "data" (0x64617461 big-endian form).
stream.Write(encoding.GetBytes("data"), 0, 4);

// NOTE to be filled in later
stream.Write(BitConverter.GetBytes(0), 0, 4);
}

/// <summary>
/// Updates wav file format header
/// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
/// </summary>
/// <param name="stream">Wav stream</param>
private void UpdateWavHeader(Stream stream)
{
if (!stream.CanSeek) throw new Exception("Can't seek stream to update wav header");

var oldPos = stream.Position;

// ChunkSize 36 + SubChunk2Size
stream.Seek(4, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4);

// Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8 This is the number of bytes in the data.
stream.Seek(40, SeekOrigin.Begin);
stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4);

stream.Seek(oldPos, SeekOrigin.Begin);
}

#endregion


}
}

0 comments on commit 0257b98

Please sign in to comment.