Adaptation/GUID-4AEF7595-17C0-513E-9568-B212E6194388.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-4AEF7595-17C0-513E-9568-B212E6194388" xml:lang="en"><title>Record
       
    13 operation</title><shortdesc>Describes the operation of the Sound Driver for sound recording.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <section id="GUID-0722033C-4BC0-45D0-B980-C1FC680BBF70"><title>Client functions</title> <p>Many aspects regarding the way
       
    15 that the Sound Driver recording operates are similar to the way it handles
       
    16 playback. One difference is how the memory location in the <xref href="GUID-51514A4B-0220-557B-9F7A-FB110CEFEF10.dita">Shared
       
    17 Chunks</xref> for the transfer is determined. In play requests, the client
       
    18 specifies the source location in the chunk for the transfer having arranged
       
    19 for the data to be loaded there prior to the request. For record requests,
       
    20 the client just requests a buffers worth of record data and allows the driver
       
    21 to decide which buffer to use for the request. </p> <p>The driver commences
       
    22 recording when the client issues the first <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-D96D7433-6CB5-3368-8B51-C19731C474AF"><apiname>RSoundSc::RecordData()</apiname></xref> request.
       
    23 However, unlike playback operation, once recording has commenced, the driver
       
    24 continues to record data into its available record buffers until it is told
       
    25 to stop. To stop the driver capturing record data, the client must either
       
    26 issue <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-16C40CF6-C84D-3901-8527-EA66842E0AAC"><apiname>RSoundSc::Pause()</apiname></xref> to temporarily suspend recording, <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-4B53ED55-EC95-35B3-B9D6-A24EF70D81F9"><apiname>RSoundSc::CancelRecordData()</apiname></xref> to
       
    27 terminate record operation, or close the driver channel altogether. </p> <p>The
       
    28 client specifies the number and size of the record buffers available to the
       
    29 driver within the shared chunk by calling either <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-1978D84C-6E2A-39C0-AF5F-17C85E5B25B4"><apiname>RSoundSc::SetBufferChunkCreate()</apiname></xref>,
       
    30 to create a buffer, or <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-46096E39-A530-3644-91F0-0B97AC3C6580"><apiname>RSoundSc::SetBufferChunkOpen()</apiname></xref> to
       
    31 open an existing buffer. </p> <p>When the driver starts recording, all the
       
    32 buffers in the shared chunk are empty, and the driver can use all of these
       
    33 available buffers. They are filled one by one, and if the client is slow to
       
    34 request the recorded data, then once the driver has filled all of the available
       
    35 empty buffers, it is forced to discard the earliest one filled and re-use
       
    36 this to continue recording data. </p> <p>Each time the client requests a buffers
       
    37 worth of recorded data with <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-D96D7433-6CB5-3368-8B51-C19731C474AF"><apiname>RSoundSc::RecordData()</apiname></xref>, it
       
    38 is given the earliest one filled. This buffer is now said to be in-use and
       
    39 unavailable to the driver for capturing. This buffer remains in-use until
       
    40 it is freed by the client with a call of <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-26F7C97B-D06A-32BE-90B3-2E6918BF3F4D"><apiname>RSoundSc::ReleaseBuffer()</apiname></xref>. </p> <p>When
       
    41 buffers are in use by the client the number of buffers available to the driver
       
    42 for capture is reduced. If the client is slow to release buffers and the number
       
    43 of available buffers falls to two then further <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-D96D7433-6CB5-3368-8B51-C19731C474AF"><apiname>RSoundSc::RecordData()</apiname></xref> requests
       
    44 fail with <codeph>KErrInUse</codeph> until the client has freed some buffers.
       
    45 The driver always needs a working set of at least two buffers in order to
       
    46 achieve uninterrupted data capture. The driver always has a current buffer
       
    47 which is actively being filled and another queued in advance. If the client
       
    48 fails to take buffers at full speed then they are discarded by the driver. </p><p><note> The
       
    49 driver does not slow down if it runs out of empty buffers. </note></p> <p><b>Buffers</b> </p> <p>The driver maintains three buffer lists: </p> <ul>
       
    50 <li id="GUID-D0B884B5-3687-5CB9-B732-1B028F0008A8"><p>free list </p> </li>
       
    51 <li id="GUID-3A3FAAA7-72C2-5A35-9F4D-3824966D3D52"><p>completed list </p> </li>
       
    52 <li id="GUID-E571D299-99C5-51D1-832E-55A88533B365"><p>in-use list. </p> </li>
       
    53 </ul> <p>A record buffer can only exist in one of these lists at any time.
       
    54 The free list contains buffers that are empty and not in use by the client.
       
    55 Once a buffer has been filled with record data it is moved into the completed
       
    56 buffer list. Here the buffer remains until it is passed back to the client
       
    57 in response to a record request. When a client is using the buffer it is deemed
       
    58 as in-use and is moved to the <i>in-use</i> list. Each time the client successfully
       
    59 calls <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-26F7C97B-D06A-32BE-90B3-2E6918BF3F4D"><apiname>RSoundSc::ReleaseBuffer()</apiname></xref> to free up a buffer then
       
    60 the driver moves this from the in-use list to the free list. </p> <p>The driver
       
    61 also maintains two record buffers which are excluded from any of the three
       
    62 lists. </p> <ul>
       
    63 <li id="GUID-3EB509DB-F35F-51E7-AAD9-8A25EEDAE604"><p>the current buffer,
       
    64 the one actively being filled with record data </p> </li>
       
    65 <li id="GUID-E109F4E5-998D-5B19-AE82-A913BBF4CED3"><p>the next buffer which
       
    66 becomes the active buffer once the current buffer is filled </p> </li>
       
    67 </ul> <p>During recording there may be DMA requests pending for both the current
       
    68 buffer and the next buffers. </p> <fig id="GUID-FBF47E94-8334-55D3-9AC0-FDAF1F9960B1">
       
    69 <title>                 The record buffer cycle               </title>
       
    70 <desc><p>The numbers one to five show the buffer cycle under normal operation,
       
    71 while the letters A to C show error induced operation. </p> </desc>
       
    72 <image href="GUID-1A92047A-3C1D-5B4C-949B-98D770F5F530_d0e32642_href.png" placement="inline"/>
       
    73 </fig> <p>When recording commences, the driver removes two buffers from the
       
    74 free list making one the current buffer and the other the next buffer (4 and
       
    75 5). </p> <p>When the current buffer is set as filled, the LDD normally adds
       
    76 this to the completed list (1). If a record error has occurred while recording
       
    77 to this buffer and it is only partially filled, or even empty then the buffer
       
    78 is still added to the completed list, as the client needs to be informed of
       
    79 the error (1). The only exception is in handling record pause, where a record
       
    80 buffer ends up being completed with no error and with no data added. In this
       
    81 case the buffer is added straight into the free list (A). </p> <p>Having added
       
    82 the current buffer to one of these lists, the driver moves the next buffer
       
    83 to the current buffer (5) and then obtains a new next buffer (4). In normal
       
    84 operation this comes from the free list but if the client is slow, this list
       
    85 may be empty and the buffer is taken from the completed list (B). This is
       
    86 a buffer overflow situation which is reported to the client as a response
       
    87 to its next <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-D96D7433-6CB5-3368-8B51-C19731C474AF"><apiname>RSoundSc::RecordData()</apiname></xref> request as <codeph>KErrOverFlow</codeph>. </p> <p>Whenever
       
    88 a buffer is filled, the driver checks if there is a record request pending
       
    89 (1). Similarly, when the driver processes a new record request it checks if
       
    90 a filled buffer is already available. In either case, if a request can be
       
    91 completed to the client then the earliest buffer completed is returned. If
       
    92 this buffer was filled successfully then it added to the in-use list (2).
       
    93 However, if an error occurred whilst filling the buffer then it is returned
       
    94 straight to the free list instead (C). </p> <p>Each time the client successfully
       
    95 calls <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-26F7C97B-D06A-32BE-90B3-2E6918BF3F4D"><apiname>RSoundSc::ReleaseBuffer()</apiname></xref> to free up a buffer then
       
    96 the driver moves this from the in-use list to the free list (3). </p> </section>
       
    97 <section id="GUID-548515F6-403D-4C99-AAA3-027C7D303C73"><title>Audio recording</title> <p><b>RecordData()</b> </p> <p>If
       
    98 the driver is not already recording data then the first <xref href="GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3.dita#GUID-B0118EDD-2B08-353E-BE92-2DC75E5622B3/GUID-D96D7433-6CB5-3368-8B51-C19731C474AF"><apiname>RSoundSc::RecordData()</apiname></xref> request
       
    99 is handled in the context of the driver DFC thread, as access to the audio
       
   100 hardware is required to enable record operation. However, for efficiency,
       
   101 subsequent record requests from the client are handled entirely in the context
       
   102 of the calling thread, as access to the audio hardware is not required to
       
   103 handle the request. The driver only has to check whether there is a filled
       
   104 record buffer already available. If there is then the driver completes the
       
   105 request straight away. If not, the driver saves the details of the request
       
   106 until a filled buffer does become available. </p> <p>Returning to the case
       
   107 of a record request where the driver is not already in the process of recording
       
   108 data, the LDD first checks whether the client has specified or supplied a
       
   109 shared chunk to the driver channel and has set the audio configuration and
       
   110 record level. If the buffer configuration has not been specified then the
       
   111 driver cannot proceed and returns <codeph>KErrNotReady</codeph>. If the audio
       
   112 configuration or record level has not been specified then the LDD applies
       
   113 default settings to the audio hardware device for each instead by calling
       
   114 the functions <xref href="GUID-E1C67F8D-1A83-36B3-A451-22F496A659C6.dita#GUID-E1C67F8D-1A83-36B3-A451-22F496A659C6/GUID-23CEDA72-E161-30C4-B8D7-DBDCBC5B9C63"><apiname>DSoundSc::SetConfig()</apiname></xref> and <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-D893A29B-1A4B-35AF-876B-84D74B7E783C"><apiname>DSoundScPdd::SetVolume()</apiname></xref> on
       
   115 the PDD. </p> <p><b>StartTransfer()</b> </p> <p>Depending
       
   116 on the mapping attributes of the shared chunk, the LDD may now need to purge
       
   117 the region of the record chunk concerned. Next the LDD calls <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-54D3CC19-0C00-3FFA-BD1A-62618D36EB20"><apiname>DSoundScPdd::StartTransfer()</apiname></xref> on
       
   118 the PDD to allow it to prepare the audio hardware device for record data transfer. </p> <p><b>TransferData()</b> </p> <p>The LDD may need to break down the record buffer
       
   119 into memory fragments. These specify a physically contiguous region and are
       
   120 manageable by the PDD as a single transfer. The LDD queues as many transfer
       
   121 fragments of the current buffer on the PDD as it can accept with a call to <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-8C79D09B-317A-3D8E-B9C2-474812F17529"><apiname>DSoundScPdd::TransferData()</apiname></xref> for
       
   122 each fragment. If all fragments from the current buffer are accepted by the
       
   123 PDD then the LDD tries to queue fragments from the next buffer. As with playback,
       
   124 to support uninterrupted transfer of audio data the PDD must be able to accept
       
   125 multiple fragments simultaneously. As long as the LDD has transfer fragments
       
   126 still to queue, it continues to call <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-8C79D09B-317A-3D8E-B9C2-474812F17529"><apiname>DSoundScPdd::TransferData()</apiname></xref> until
       
   127 the PDD signals that it has temporarily reached its capacity by returning <codeph>KErrNotReady</codeph>. </p> <p><b>RecordCallBack()</b> </p> <p>Each time the PDD completes the transfer
       
   128 of a fragment from a record buffer, it must signal this event back to the
       
   129 LDD by calling the function <xref href="GUID-5807543D-A30F-3EB9-8F28-91A623B0D484.dita#GUID-5807543D-A30F-3EB9-8F28-91A623B0D484/GUID-9112E399-DC3C-334F-BE16-B5F42216F903"><apiname>DSoundScLdd::RecordCallBack()</apiname></xref>.
       
   130 This must always be called in the context of the driver DFC thread. In executing <xref href="GUID-5807543D-A30F-3EB9-8F28-91A623B0D484.dita#GUID-5807543D-A30F-3EB9-8F28-91A623B0D484/GUID-434E378F-0C48-39D9-8FB8-9831A1F704C0"><apiname>DSoundScLdd::RecordCallback()</apiname></xref>,
       
   131 the LDD checks whether the entire transfer for the current buffer is now complete.
       
   132 If so, depending on the mapping attributes of the shared chunk, the LDD may
       
   133 need to purge the region of the record client. The LDD attempts to queue further
       
   134 fragments on the PDD, by calling <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-8C79D09B-317A-3D8E-B9C2-474812F17529"><apiname>DSoundScPdd::TransferData()</apiname></xref>,
       
   135 which should now have the capability to accept more transfers. So, the PDD
       
   136 should be written to handle calls to <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-8C79D09B-317A-3D8E-B9C2-474812F17529"><apiname>DSoundScPdd::TransferData()</apiname></xref> within
       
   137 its call back to <xref href="GUID-5807543D-A30F-3EB9-8F28-91A623B0D484.dita#GUID-5807543D-A30F-3EB9-8F28-91A623B0D484/GUID-434E378F-0C48-39D9-8FB8-9831A1F704C0"><apiname>DSoundScLdd::RecordCallback()</apiname></xref>. </p> </section>
       
   138 <section id="GUID-7B5CF9A4-8527-4C76-96CD-C03F861AF3BF"><title>Pause and resume audio recording</title> <p>The client can
       
   139 temporarily halt the progress of audio record at any time by issuing <xref href="GUID-5807543D-A30F-3EB9-8F28-91A623B0D484.dita#GUID-5807543D-A30F-3EB9-8F28-91A623B0D484/GUID-D912620F-9C51-3AFC-8A59-31AF9455AC4A"><apiname>DSoundScLdd::Pause()</apiname></xref>.
       
   140 To configure the audio hardware device to halt recording, the LDD calls <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-0608766F-2645-3E28-B804-BD4B953DB5FF"><apiname>DSoundScPdd::PauseTransfer()</apiname></xref> on
       
   141 the PDD. This time, any active transfer should be aborted by the PDD. If a
       
   142 recording is halted the PDD must signal this event with a single call of the
       
   143 LDD function <xref href="GUID-3731902C-9C34-3FAE-8F82-9F9493C2C2E7.dita#GUID-3731902C-9C34-3FAE-8F82-9F9493C2C2E7/GUID-73F74080-6219-3D9A-BA56-735A17A9ABA0"><apiname>DSOundScLdd::RecordCallback()</apiname></xref>, which reports
       
   144 back any partial data already received. In this case, if transfer is resumed
       
   145 later, the LDD issues a new <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-8C79D09B-317A-3D8E-B9C2-474812F17529"><apiname>DSoundScPdd::TransferData()</apiname></xref> request
       
   146 to commence data transfer after calling <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-C692BF61-FA3D-3B85-BCC6-1248C9C7D9BF"><apiname>DSoundScPdd::ResumeTransfer()</apiname></xref>.
       
   147 As access to the hardware is required in both cases, pause and resume are
       
   148 handled in the context of the driver DFC thread. </p> </section>
       
   149 <section id="GUID-BA951968-290F-4DA5-842A-2004664B1139"><title>Error handling during recording</title> <p>If the PDD reports
       
   150 an error when setting up the audio hardware device for recording then the
       
   151 LDD immediately completes the first record request back to the client returning
       
   152 the error value as the result. It will not restart record data transfer unless
       
   153 it receives a further record request from the client. </p> <p>If the PDD reports
       
   154 an error when commencing the transfer of a record fragment or as the result
       
   155 of the transfer of a record fragment, then the LDD ceases transfer to that
       
   156 record buffer and instead reports the error back to the client. The error
       
   157 is returned in response to the record request which corresponds with that
       
   158 buffer. </p> <p>Unexpected errors from the PDD are returned to the LDD via
       
   159 the functions <xref href="GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424.dita#GUID-61CC68CB-A01D-3CA0-93D9-F3717ABD6424/GUID-8C79D09B-317A-3D8E-B9C2-474812F17529"><apiname>DSoundScPdd::TransferData()</apiname></xref> and <xref href="GUID-5807543D-A30F-3EB9-8F28-91A623B0D484.dita#GUID-5807543D-A30F-3EB9-8F28-91A623B0D484/GUID-434E378F-0C48-39D9-8FB8-9831A1F704C0"><apiname>DSoundScLdd::RecordCallback()</apiname></xref>. </p> <p>The
       
   160 LDD does not try to cancel the transfer of other fragments for the same buffer
       
   161 that are already queued on the PDD, but it ignores their outcome. However,
       
   162 the LDD does try to carry on with the transfer to other available record buffers. </p> </section>
       
   163 </conbody></concept>