[Multimedia] Add guide for the AudioIO 37/153237/3
authorcoderhyme <jhyo.kim@samsung.com>
Thu, 28 Sep 2017 06:25:28 +0000 (15:25 +0900)
committerEditor Lionbridge <TizenEditor.SEL@lionbridge.com>
Fri, 29 Sep 2017 07:29:39 +0000 (10:29 +0300)
PS2: Reviewed
PS3: Fixed the prerequisite info

Change-Id: Ie9a580acde8bd6db22307f072d3df66e18d2eb97
Signed-off-by: coderhyme <jhyo.kim@samsung.com>
org.tizen.guides/html/dotnet/media/audio_io.htm [new file with mode: 0644]

diff --git a/org.tizen.guides/html/dotnet/media/audio_io.htm b/org.tizen.guides/html/dotnet/media/audio_io.htm
new file mode 100644 (file)
index 0000000..27b9320
--- /dev/null
@@ -0,0 +1,393 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+       <meta http-equiv="X-UA-Compatible" content="IE=9" />
+       <link rel="stylesheet" type="text/css" href="../../css/styles.css" />
+       <link rel="stylesheet" type="text/css" href="../../css/snippet.css" />
+       <script type="text/javascript" src="../../scripts/snippet.js"></script>
+       <script type="text/javascript" src="../../scripts/jquery.util.js" charset="utf-8"></script>
+       <script type="text/javascript" src="../../scripts/common.js" charset="utf-8"></script>
+       <script type="text/javascript" src="../../scripts/core.js" charset="utf-8"></script>
+       <script type="text/javascript" src="../../scripts/search.js" charset="utf-8"></script>
+
+       <title>Raw Audio Playback and Recording</title>
+
+</head>
+
+<body onload="prettyPrint()" style="overflow: auto;">
+
+<div id="toc-navigation">
+       <div id="toc_border"><div id="toc">
+               <p class="toc-title">Dependencies</p>
+               <ul class="toc">
+                       <li>Tizen 4.0 and Higher</li>
+               </ul>
+
+               <p class="toc-title">Content</p>
+                       <ul class="toc">
+                       <li><a href="#play_pcm">Audio Output</a></li>
+                       <li><a href="#record_pcm">Audio Input</a></li>
+                       <li><a href="#prerequisites">Prerequisites</a></li>
+                       <li>Playback
+                <ul class="toc">
+                                       <li><a href="#simple_playback">Managing Synchronous Playback</a></li>
+                                       <li><a href="#async_playback">Managing Asynchronous Playback</a></li>
+                </ul>
+            </li>
+            <li>Recording
+                <ul class="toc">
+                                       <li><a href="#simple_recording">Managing Synchronous Recording</a></li>
+                                       <li><a href="#async_recording">Managing Asynchronous Recording</a></li>
+                               </ul>
+            </li>
+                       </ul>
+
+               <p class="toc-title">Related Info</p>
+               <ul class="toc">
+                       <li><a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AsyncAudioCapture.html">Tizen.Multimedia.AsyncAudioCapture Class</a></li>
+                       <li><a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AudioCapture.html">Tizen.Multimedia.AudioCapture Class</a></li>
+                       <li><a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AudioPlayback.html">Tizen.Multimedia.AudioPlayback Class</a></li>
+               </ul>
+       </div></div>
+</div>
+
+<div id="container"><div id="contents"><div class="content">
+
+<h1>Raw Audio Playback and Recording</h1>
+<p>Pulse Code Modulated (PCM) data contains uncompressed audio. You can play and record uncompressed audio data both synchronously and asynchronously.</p>
+  <p>The main uncompressed audio management features are:</p>
+  <ul>
+       <li>Playing uncompressed audio
+       <p>You can <a href="#play_pcm">play uncompressed audio</a> in your application.</p></li>
+    <li>Recording uncompressed audio
+    <p>You can <a href="#record_pcm">record uncompressed audio</a> synchronously or asynchronously.</p></li>
+  </ul>
+
+ <h2 id="play_pcm">Audio Output</h2>
+
+<p>The <a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AudioPlayback.html">Tizen.Multimedia.AudioPlayback</a> class enables your application to play uncompressed audio. You can <a href="#simple_playback">play audio synchronously</a>, or <a href="#async_playback">do it asynchronously</a>.</p>
+  <p>Your application must define the following PCM data settings:</p>
+  <ul>
+   <li>Audio channels:
+    <ul>
+     <li>Mono (1 channel)</li>
+     <li>Stereo (2 channels)</li>
+    </ul> </li>
+   <li>Audio sample type:
+    <ul>
+     <li>Unsigned 8-bit PCM</li>
+     <li>Signed 16-bit little endian PCM</li>
+    </ul> </li>
+   <li>Audio sample rate:
+   <ul>
+    <li>8000 ~ 48000 Hz</li>
+   </ul> </li>
+  </ul>
+  <p>To support various low-end Tizen devices, the application must follow certain guidelines:</p>
+  <ul>
+   <li>Do not use excessive instances of the <code>Tizen.Multimedia.AudioPlayback</code> class.
+   <p>Using many <code>Tizen.Multimedia.AudioPlayback</code> class instances decreases application performance, because processing audio data for re-sampling and mixing imposes a heavy burden on the system.</p>
+   </li>
+   <li>Use the device-preferred PCM format.
+   <p>To reduce the processing overhead, select the PCM format based on the target device preference (for example, signed 16-bit little endian, stereo, 44100 Hz).</p>
+    <p>Using the preferred format reduces internal operations, such as converting audio samples from mono to stereo or re-sampling audio frequency to fit the target device's input sample rate.</p>
+    </li>
+    <li>Reduce event delay and remove glitches.
+    <p>The <code>Tizen.Multimedia.AudioPlayback</code> class instance works recursively, using events. The smaller the buffer size, the more often events are generated. If you use a small buffer in addition to other resources (for example, a timer or sensor), application performance decreases because the events cause delays. To prevent problems, set an appropriate write buffer size.</p>
+    <p>To guarantee that the events of the <code>Tizen.Multimedia.AudioPlayback</code> class work independently, create a <code>Tizen.Multimedia.AudioPlayback</code> class instance in the event thread.</p>
+    </li>
+    <li>Use double buffering.
+    <p>Use the double-buffering mechanism to reduce latency. It works by first writing the data twice before starting playback. After starting, whenever the event handler is called, you can write additional data.</p>
+    </li>
+       <li>Save power.
+       <p>If audio playback has stopped for a long time, such as because the screen has switched off or there is no audio data, call the <code>Unprepare()</code> method of the <code>Tizen.Multimedia.AudioPlayback</code> class to pause the stream and save power. The device cannot go into the sleep mode while the <code>Tizen.Multimedia.AudioPlayback</code> instance is in the <code>Running</code> state.</p>
+    </li>
+  </ul>
+
+
+<h2 id="record_pcm">Audio Input</h2>
+
+<p>You can enable your application to record uncompressed audio from a microphone-type input device. You can <a href="#simple_recording">record audio synchronously</a> with the <a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AudioCapture.html">Tizen.Multimedia.AudioCapture</a> class, or <a href="#async_recording">do it asynchronously</a> with the <a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AsyncAudioCapture.html">Tizen.Multimedia.AsyncAudioCapture</a> class.</p>
+
+  <p>Audio data is captured periodically. To receive the audio PCM data from the input device, you must implement the audio capture interface to notify the application of audio data events, such as when the audio data buffer is full.</p>
+  <p>Before recording audio, you must define the following PCM data settings:</p>
+  <ul>
+   <li>Input device type:
+    <ul>
+     <li>Microphone</li>
+    </ul> </li>
+   <li>Audio channels:
+    <ul>
+     <li>Mono (1 channel)</li>
+     <li>Stereo (2 channels)</li>
+    </ul> </li>
+   <li>Audio sample type:
+    <ul>
+     <li>Unsigned 8-bit PCM</li>
+     <li>Signed 16-bit little endian PCM</li>
+    </ul> </li>
+   <li>Audio sample rate:
+   <ul>
+    <li>8000 ~ 48000 Hz</li>
+   </ul></li>
+  </ul>
+
+
+<h2 id="prerequisites">Prerequisites</h2>
+
+<p>To make your application visible in the Tizen Store only for devices that support a microphone, the application must specify the following feature in the <code>tizen-manifest.xml</code> file:</p>
+<pre class="prettyprint">
+&lt;feature name="http://tizen.org/feature/microphone"/&gt;
+</pre>
+
+<h2 id="simple_playback" name="simple_playback">Managing Synchronous Playback</h2>
+
+<p>Because the synchronous playback process blocks other processes running in the same thread, launching a playback process from the application main thread can make the application unresponsive. To prevent this, launch the playback process from its own thread.</p>
+
+<p>To play audio:</p>
+
+<ol>
+<li><p>Prepare the audio output device and start the playback process using the <code>Prepare()</code> method of the <a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AudioPlayback.html">Tizen.Multimedia.AudioPlayback</a> class:</p>
+
+<pre class="prettyprint">
+var audioPlayback = new AudioPlayback(44100, AudioChannel.Mono, AudioSampleType.S16Le);
+
+/// Prepare the audio output device (start the hardware playback process)
+audioPlayback.Prepare();
+</pre>
+
+<p>The hardware device prepares its internal output buffer for playback. Playback begins when the internal output buffer starts receiving audio data.</p>
+
+</li>
+<li><p>To start playing the recorded audio, copy the audio data from the local buffer to the internal output buffer using the <code>Write()</code> method of the <code>Tizen.Multimedia.AudioCapture</code> class:</p>
+
+<pre class="prettyprint">
+int bytesWritten = audioPlayback.Write(buffer);
+</pre>
+<p>The returned value represents the number of bytes written to the internal output buffer.</p>
+</li>
+
+<li><p>Stop the playback process using the <code>Unprepare()</code> method of the <code>Tizen.Multimedia.AudioCapture</code> class:</p>
+
+<pre class="prettyprint">
+audioPlayback.Unprepare();
+</pre></li>
+</ol>
+
+<h2 id="async_playback" name="async_playback">Managing Asynchronous Playback</h2>
+
+<p>The asynchronous playback process uses the <code>BufferAvailable</code> event of the <a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AudioPlayback.html">Tizen.Multimedia.AudioPlayback</a> class to play the recorded audio. The event is raised for each recorded audio chunk. In the following example, the audio data is read from a stream.</p>
+
+<p>To start playing the recorded audio:</p>
+
+<ol><li>
+<p>Add an event handler for the <code>BufferAvailable</code> event:</p>
+
+<pre class="prettyprint">
+audioPlayback.BufferAvailable += OnBufferAvailable;
+</pre>
+</li>
+
+<li>
+<p>Prepare the audio output device and start the playback process using the <code>Prepare()</code> method of the <code>Tizen.Multimedia.AudioCapture</code> class:</p>
+
+<pre class="prettyprint">
+audioPlayback.Prepare();
+</pre>
+<p>The hardware device prepares its internal output buffer for playback.</p>
+</li>
+<li>
+
+<p>Play audio from a stream.</p>
+<p>Read audio data from the stream and write it to the internal output buffer using the <code>Write()</code> method of the <code>Tizen.Multimedia.AudioPlayback</code> class. Playback begins when the internal output buffer starts receiving the audio data.</p>
+
+<pre class="prettyprint">
+Stream stream;
+
+void OnBufferAvailable(object sender, AudioPlaybackBufferAvailableEventArgs args)
+{
+    if (args.Length &gt; 0)
+    {
+        try
+        {
+            /// Allocate a local buffer for reading the audio data from the stream
+            byte[] buffer = new byte[args.Length];
+
+            /// Read audio data from the stream and store it in the local buffer
+            stream.Read(buffer, 0, args.Length);
+
+            /// Copy the audio data from the local buffer
+            /// to the internal output buffer (starts playback)
+            audioPlayback.Write(buffer);
+        }
+        catch(Exception e)
+        {
+            Tizen.Log.Error(LOG_TAG, "Failed to write. " + e);
+        }
+    }
+}
+</pre></li>
+<li><p>Stop the playback process using the <code>Unprepare()</code> method of the <code>Tizen.Multimedia.AudioCapture</code> class:</p>
+
+<pre class="prettyprint">
+/// Stop the hardware playback process
+audioPlayback.Unprepare(output);
+</pre>
+<p>The device no longer raises the event.</p>
+</li>
+</ol>
+
+
+<h2 id="simple_recording" name="simple_recording">Managing Synchronous Recording</h2>
+
+<p>Before starting the synchronous recording process, you need to know the size of the buffer where the recorded audio data is to be saved, based on the expected recording duration. The recording process ends once it has read the specified number of bytes.</p>
+
+<p>To calculate and set the required buffer size, use one of the following options:</p>
+
+<ul>
+
+<li><p>Calculate the buffer size based on the recommendation of the sound server, such as PulseAudio:</p>
+
+<ol><li>
+<p>Retrieve the recommended buffer size using the <code>GetBufferSize()</code> method of the <a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AudioCapture.html">Tizen.Multimedia.AudioCapture</a> class:</p>
+
+<pre class="prettyprint">
+var audioCapture = new AudioCapture(44100, AudioChannel.Mono, AudioSampleType.S16Le);
+
+int bufferSize = audioCapture.GetBufferSize();
+</pre>
+
+<p>If no exception is thrown, the method returns the preferred size in bytes, based on the specified audio parameters.</p>
+<p>The recommended buffer size depends on the device. The size can be different for mobile, wearable, and TV devices.</p>
+</li>
+
+<li>
+
+<p>Set the buffer size to correspond to the desired recording duration.</p>
+
+<p>For the device in this example, the <code>GetBufferSize()</code> method returns the recommended buffer size for 100 milliseconds of recording time. To determine the total recommended buffer size, multiply the recommended buffer size by 10 (to get the buffer size per second) and by the length of the recording in seconds:</p>
+
+<pre class="prettyprint">
+const int RecordingSec = 5;
+
+bufferSize *= 10 * RecordingSec;
+</pre>
+
+</li>
+
+</ol></li>
+<li>
+<p>Calculate the required buffer size explicitly:</p>
+
+<pre class="prettyprint">
+int bufferSize = AudioCapture.SampleRate * (audioCapture.Channel == AudioChannel.Stereo ? 2 : 1) *
+    (audioCapture.SampleType == AudioSampleType.S16Le ? 2 : 1);
+
+bufferSize *= RecordingSec;
+</pre>
+</li></ul>
+
+<p>The synchronous recording process blocks other processes running in the same thread. Launching a recording process from the application main thread can make the application unresponsive. To prevent this, launch the recording process from its own thread.</p>
+
+<p>To record audio:</p>
+
+<ol><li>
+<p>Prepare the audio input device and start the recording process using the <code>Prepare()</code> method of the <code>Tizen.Multimedia.AudioCapture</code> class:</p>
+
+<pre class="prettyprint">
+audioCapture.Prepare();
+</pre>
+<p>The hardware device starts buffering the audio recorded by the audio input device. The audio data is buffered to the internal input buffer.</p>
+</li>
+<li><p>Read the audio data from the internal input buffer using the <code>Read()</code> method:</p>
+
+<pre class="prettyprint">
+byte[] buffer = audioCapture.Read(bufferSize);
+</pre>
+
+<p>The <code>Read()</code> method can behave in the following ways:</p>
+<ul>
+<li>If the method is called immediately after preparing the audio input device, it blocks the thread that it was launched from until it reads bytes specified.</li>
+<li>If the method is called with a delay long enough to allow the internal input buffer to store more audio data than the specified size, the method returns immediately without blocking its thread.</li></ul>
+</li>
+<li><p>Stop the recording process using the <code>Unprepare()</code> method:</p>
+
+<pre class="prettyprint">
+audioCapture.Unprepare();
+</pre></li>
+</ol>
+
+<h2 id="async_recording" name="async_recording">Managing Asynchronous Recording</h2>
+
+<p>The asynchronous recording process uses an event to store the audio recorded by the audio input device. The event is raised for each recorded audio chunk. In this use case, the audio data is stored in a stream.</p>
+
+<p>To start recording audio:</p>
+
+<ol><li><p>Add an event handler for the <code>DataAvailable</code> event of the <a href="https://developer.tizen.org/dev-guide/csapi/classTizen_1_1Multimedia_1_1AsyncAudioCapture.html">Tizen.Multimedia.AsyncAudioCapture</a> class:</p>
+
+<pre class="prettyprint">
+var asyncAudioCapture = new AsyncAudioCapture(44100, AudioChannel.Mono, AudioSampleType.S16Le);
+
+/// Add an event handler invoked asynchronously for each recorded audio chunk
+asyncAudioCapture.DataAvailable += OnDataAvailable;
+</pre>
+</li>
+
+<li>
+<p>Prepare the audio input device and start the recording process using the <code>Prepare()</code> method of the <code>Tizen.Multimedia.AsyncAudioCapture</code> class:</p>
+
+<pre class="prettyprint">
+asyncAudioCapture.Prepare();
+</pre>
+
+<p>The hardware device starts buffering the audio recorded by the audio input device. The audio data is buffered to the internal input buffer. The event is raised for each audio data chunk.</p>
+</li>
+
+<li>
+<p>To store the recorded audio data:</p>
+
+<pre class="prettyprint">
+Stream stream;
+
+/// Event handler invoked for each recorded audio chunk
+void OnDataAvailable(object sender, AudioDataAvailableEventArgs args)
+{
+    /// Write the recorded audio data to the stream
+    stream.Write(args.Data, 0, args.Data.Length);
+}
+</pre></li>
+<li><p>Stop the recording process using the <code>Unprepare()</code> method:</p>
+
+<pre class="prettyprint">
+asyncAudioCapture.Unprepare();
+</pre>
+<p>The device no longer raises the event.</p>
+</li>
+
+</ol>
+
+<script type="text/javascript" src="../../scripts/jquery.zclip.min.js"></script>
+<script type="text/javascript" src="../../scripts/showhide.js"></script>
+</div></div></div>
+
+
+<a class="top sms" href="#"><img src="../../images/btn_top.gif" alt="Go to top"/></a>
+
+<div id="footer">
+<p class="footer">Except as noted, this content - excluding the Code Examples - is licensed under <a href="http://creativecommons.org/licenses/by/3.0/legalcode" target="_blank">Creative Commons Attribution 3.0</a> and all of the Code Examples contained herein are licensed under <a href="https://www.tizen.org/bsd-3-clause-license" target="_blank">BSD-3-Clause</a>.<br/>For details, see the <a href="https://www.tizen.org/content-license" target="_blank">Content License</a>.</p>
+</div>
+
+<script type="text/javascript">
+var _gaq = _gaq || [];
+_gaq.push(['_setAccount', 'UA-25976949-1']);
+_gaq.push(['_trackPageview']);
+(function() {
+var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+})();
+</script>
+
+
+</body></html>