OpenNI 1.5.4: NiAudioSample.cpp - sample program

OpenNI

NiAudioSample.cpp - sample program

Source file: Click the following link to view the source code file:

  • NiAudioSample.cpp

This section describes an OpenNI sample program for using the Audio interface.

The documentation describes the sample program's code from the top of the program file(s) to bottom.

This documentation item describes only OpenNI code features. Third party features, e.g., GL code, may be ignored. However, place holders as section headings appear in place of complete functions or large code blocks that are not OpenNI specific or key to understanding the logic of the sample program. These place holders are section headings with minimal text to enable the reader to identify the original program structure when studying the documentation.

Every OpenNI feature is described the first time it appears in this sample program. Further appearances of the same feature are not described again.

Macro Declarations

At the top of the program is a macro utility declaration, which calls OpenNI methods. It is described below. However, for the sake of conciseness, the rest of this documentation skips calls to this macro.

The CHECK_RC() macro checks whether the most recent OpenNI operation was successful or returned an error result. On error, the xnGetStatusString() method converts the OpenNI error return code to the corresponding error string for printing, and the current function exits.

            #define CHECK_RC(rc, what) \
                if (rc != XN_STATUS_OK)                                     \
                {                                                           \
                    printf("%s failed: %s\n", what, xnGetStatusString(rc)); \
                    return rc;                                              \
                }

Declaration of File Path

In the following definitions, SAMPLE_XML_PATH is for the path to an OpenNI XML script input file for building a production graph. The production graph is a network of production nodes and is the principal OpenNI object model. See The Production Graph for more about the production graph.

            #define SAMPLE_XML_PATH "../../../../Data/SamplesConfig.xml"

"Declaration Block" section

The reader may find it convenient to study the global declaration block before continuing to study the code statements. The global declaration block is documented later in this section, corresponding to its position in the program file – see "Declaration Block" section.

enum Mode

The following declaration defines the program mode, whether whether it is recording an OpenNI data generation session or whether it is playing a recording.

            enum Mode
            {
                MODE_PLAY,
                MODE_RECORD,
            };

This declaration is not OpenNI specific.

printUsage() method

This function is not OpenNI specific.

play() method - Play Audio

This routine gets an array of AudioGenerators, takes the first one, and constantly reads data from it and sends it to be played.

The following code block gets the first AudioGenerator node's wave output mode. It is received in an xn::XnWaveOutputMode, which comprises: bits per sample, channel, and sample rate. This information is then used for setting up the audio output buffers for collecting the generated play data and for setting up the hardware audio output channel.

            XnWaveOutputMode waveMode;
            nRetVal = aGens[0].GetWaveOutputMode(waveMode);
            CHECK_RC(nRetVal, "Failed getting wave output mode");

The above completes the initialization. The following code is the main program loop.

The application calls an 'Update Data()' method, in this case the node's WaitAndUpdateData, to make a new frame available for getting. The application can then get the data (for example, using a metadata GetData() method).

            nRetVal = aGens[0].WaitAndUpdateData();

Assuming the above call succeeded, the application then gets the size of the audio data that was generated by the AudioGenerator node.

            XnUInt32 nBufferSize = aGens[0].GetDataSize();

The next OpenNI statements copy the AudioGenerator node's data into a prepared buffer to be sent to the machine sound card. xnOSMemCopy is OpenNI memory copy routine.

            xnOSMemCopy(pHeader->lpData, aGens[0].GetAudioBuffer(), nBufferSize);
            pHeader->dwBufferLength = nBufferSize;

record() method - Record Audio

This method gets a list of audio generators, and records to a separate file the data generated by each generator . The following code block creates files named with the names of the AudioGenerator nodes.

            XN_FILE_HANDLE aFiles[nSupportedNodes];
            for (XnUInt32 i = 0; i < nNodes; ++i)
            {
                XnChar strFileName[XN_FILE_MAX_PATH];
                sprintf(strFileName, "audio.%s.pcm", aGens[i].GetName());
                nRetVal = xnOSOpenFile(strFileName, XN_OS_FILE_WRITE, &aFiles[i]);
                CHECK_RC(nRetVal, "Open file");
            }

The application then calls an 'Update Data' method, in this case xn::Context.WaitAnyUpdateAll(), to update all generator nodes in the context to the latest available data, first waiting for any of the nodes to have new data available. The first call is used just to flush the node.

            context.WaitAnyUpdateAll();

The following loop checks which node has new data and writes it to a file. The IsDataNew() method returns whether a node's frame data was updated by the most recent call to the WaitAnyUpdateAll() method.

            XN_FILE_HANDLE aFiles[nSupportedNodes];
               ...
               ...
            for (XnUInt32 i = 0; i < nNodes; ++i)
            {
                if (aGens[i].IsDataNew())
                {
                    nRetVal = xnOSWriteFile(aFiles[i], aGens[i].GetAudioBuffer(), aGens[i].GetDataSize());
                    CHECK_RC(nRetVal, "Write to file");
                }
            }

Main Program

"Declaration Block" section

The declaration block at the top of the main program declares a xn::Context object, an xn::EnumerationErrors object, and an xn::ScriptNode object. The Context object is a workspace in which the application builds an OpenNI production graph. the xn::EnumerationErrors object is for collecting errors from any of the OpenNI functions. Also declared is an OpenNI status flag for collecting return values from method calls. the xn::ScriptNode object loads an XML script from a file or string, and then runs the XML script to build a production graph.

                XnStatus nRetVal = XN_STATUS_OK;
                Context context;
                EnumerationErrors errors;
                  ...
                ScriptNode scriptNode;

Main Code Section

In the following, the InitFromXmlFile() method is a shorthand combination of two other initialization methods – Init() and then RunXmlScriptFromFile() – which initializes the context object and then creates a production graph from an XML file.

                nRetVal = context.InitFromXmlFile(SAMPLE_XML_PATH, scriptNode);         

The following code block tests whether a production graph was created. If not, the reason is reported as a list of one or more errors in the errors object.

                if (nRetVal == XN_STATUS_NO_NODE_PRESENT)
                {
                    XnChar strError[1024];
                    errors.ToString(strError, 1024);
                    printf("%s\n", strError);
                    return (nRetVal);
                }

The following code block searches for xn::AudioGenerator nodes in the production graph. The nodes are returned in the xn::NodeInfoList object. This object is a list xn::NodeInfo objects, each containing information about a node found in the above EnumerateExistingNodes() call.

                NodeInfoList list;
                nRetVal = context.EnumerateExistingNodes(list, XN_NODE_TYPE_AUDIO);
                CHECK_RC(nRetVal, "Enumerate audio nodes"); 
                AudioGenerator gens[nSupportedNodes];
                XnUInt32 nNodes = 0;

The following declarations and statements get all the xn::AudioGenerator nodes that were found by the EnumerateExistingNodes() call. The gens array receives all the nodes, and they are counted by the nNodes variable. (Currently, only a single AudioGenerator node is supported for playing at at once.)

                AudioGenerator gens[nSupportedNodes];
                XnUInt32 nNodes = 0;
                   ...
                for (NodeInfoList::Iterator it = list.Begin(); it != list.End(); ++it)
                {
                    NodeInfo info = *it;
                    nRetVal = info.GetInstance(gens[nNodes]);
                    CHECK_RC(nRetVal, "Get audio node");
                    nNodes++;
                }
Generated on Wed May 16 2012 10:16:06 for OpenNI 1.5.4 by   doxygen 1.7.5.1