diff --git a/framework/CordovaLib/Commands/AudioFormatsHelper.cs b/framework/CordovaLib/Commands/AudioFormatsHelper.cs new file mode 100644 index 0000000..f93340f --- /dev/null +++ b/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 +{ + /// + /// Provides extra functionality to support different audio formats. + /// + public static class AudioFormatsHelper + { + #region Wav + /// + /// Adds wav file format header to the stream + /// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ + /// + /// The stream + /// Sample Rate + 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); + } + + /// + /// Updates wav file format header + /// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ + /// + /// Wav stream + 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 + } +} diff --git a/framework/WP7CordovaClassLib.csproj b/framework/WP7CordovaClassLib.csproj index 62ee745..a3257e3 100644 --- a/framework/WP7CordovaClassLib.csproj +++ b/framework/WP7CordovaClassLib.csproj @@ -184,6 +184,7 @@ CordovaLib\UI\VideoRecorder.xaml.cs VideoRecorder.xaml + diff --git a/templates/standalone/cordovalib/Commands/AudioPlayer.cs b/templates/standalone/cordovalib/Commands/AudioPlayer.cs index e57157a..4df878f 100644 --- a/templates/standalone/cordovalib/Commands/AudioPlayer.cs +++ b/templates/standalone/cordovalib/Commands/AudioPlayer.cs @@ -168,7 +168,7 @@ public void startRecording(string filePath) this.buffer = new byte[recorder.GetSampleSizeInBytes(this.recorder.BufferDuration)]; this.recorder.BufferReady += new EventHandler(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); @@ -495,7 +495,7 @@ private void SaveAudioClipToLocalStorage() return; } - this.UpdateWavHeader(this.memoryStream); + this.memoryStream.UpdateWavStream(); try { @@ -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/ - - /// - /// Adds wav file format header to the stream - /// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ - /// - /// Wav stream - /// Sample Rate - 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); - } - - /// - /// Updates wav file format header - /// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ - /// - /// Wav stream - 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 /// diff --git a/templates/standalone/cordovalib/Commands/ImageExifHelper.cs b/templates/standalone/cordovalib/Commands/ImageExifHelper.cs index 626726b..ed8d89b 100644 --- a/templates/standalone/cordovalib/Commands/ImageExifHelper.cs +++ b/templates/standalone/cordovalib/Commands/ImageExifHelper.cs @@ -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 { diff --git a/templates/standalone/cordovalib/Commands/Notification.cs b/templates/standalone/cordovalib/Commands/Notification.cs index acbda68..49ca3fe 100644 --- a/templates/standalone/cordovalib/Commands/Notification.cs +++ b/templates/standalone/cordovalib/Commands/Notification.cs @@ -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 { diff --git a/templates/standalone/cordovalib/UI/AudioRecorder.xaml.cs b/templates/standalone/cordovalib/UI/AudioRecorder.xaml.cs index b3c69dd..fbd74a6 100644 --- a/templates/standalone/cordovalib/UI/AudioRecorder.xaml.cs +++ b/templates/standalone/cordovalib/UI/AudioRecorder.xaml.cs @@ -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 @@ -122,7 +123,7 @@ private void StartRecording() this.microphone.BufferReady += new EventHandler(MicrophoneBufferReady); this.memoryStream = new MemoryStream(); - this.WriteWavHeader(this.memoryStream, this.microphone.SampleRate); + this.memoryStream.InitializeWavStream(this.microphone.SampleRate); this.duration = new TimeSpan(0); @@ -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 @@ -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/ - - /// - /// Adds wav file format header to the stream - /// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ - /// - /// Wav stream - /// Sample Rate - 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); - } - - /// - /// Updates wav file format header - /// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ - /// - /// Wav stream - 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 - - } } \ No newline at end of file