Permalink
Browse files

audio: Add support for uploading firmware; refactor some other things

This patch separates audio support out into a separate libfreenect-audio.h
header.  It updates the CMake lists to place audio support files (either
fwfetcher.py or audios.bin) in the appropriate install folder, rather
than under $PREFIX/lib.

To support uploading the audio firmware, I added two new calls to our
libusb wrapper - we need bulk transfer support to actually send the
firmware, and we need to count the number of interfaces in the current
configuration to distinguish a device in the bootloader from one which has
already had firmware uploaded.  These calls will need to be implemented
in libusbemu before audio will work on Windows.

Signed-off-by: Drew Fisher <drew.m.fisher@gmail.com>
  • Loading branch information...
zarvox committed Apr 12, 2011
1 parent 9c6e73a commit b886db05abe808e73eb0c5123f28d12d82969416
Showing with 527 additions and 87 deletions.
  1. +3 −0 CMakeLists.txt
  2. +2 −1 examples/wavrecord.c
  3. +120 −0 include/libfreenect-audio.h
  4. +0 −79 include/libfreenect.h
  5. +8 −4 src/CMakeLists.txt
  6. +1 −0 src/audio.c
  7. +28 −1 src/core.c
  8. +5 −1 src/freenect_internal.h
  9. +277 −0 src/loader.c
  10. +60 −0 src/loader.h
  11. +19 −0 src/usb_libusb10.c
  12. +4 −1 src/usb_libusb10.h
View
@@ -178,6 +178,9 @@ IF ( BUILD_CPACK )
include(CPack)
INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/libfreenect.a" DESTINATION ${PROJECT_LIBRARY_INSTALL_DIR})
+ if (BUILD_AUDIO)
+ INSTALL(FILES "include/libfreenect-audio.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR})
+ endif()
INSTALL(FILES "include/libfreenect.h" DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR})
INSTALL(FILES "APACHE20" DESTINATION "share/doc/${CPACK_PACKAGE_NAME}")
INSTALL(FILES "GPL2" DESTINATION "share/doc/${CPACK_PACKAGE_NAME}")
View
@@ -25,6 +25,7 @@
*/
#include "libfreenect.h"
+#include "libfreenect-audio.h"
#include <stdio.h>
#include <signal.h>
@@ -74,7 +75,7 @@ int main(int argc, char** argv) {
printf("freenect_init() failed\n");
return 1;
}
- freenect_set_log_level(f_ctx, FREENECT_LOG_DEBUG);
+ freenect_set_log_level(f_ctx, FREENECT_LOG_SPEW);
int nr_devices = freenect_num_devices (f_ctx);
printf ("Number of devices found: %d\n", nr_devices);
View
@@ -0,0 +1,120 @@
+/*
+ * This file is part of the OpenKinect Project. http://www.openkinect.org
+ *
+ * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file
+ * for details.
+ *
+ * This code is licensed to you under the terms of the Apache License, version
+ * 2.0, or, at your option, the terms of the GNU General Public License,
+ * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses,
+ * or the following URLs:
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.gnu.org/licenses/gpl-2.0.txt
+ *
+ * If you redistribute this file in source form, modified or unmodified, you
+ * may:
+ * 1) Leave this header intact and distribute it under the same terms,
+ * accompanying it with the APACHE20 and GPL20 files, or
+ * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or
+ * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file
+ * In all cases you must keep the copyright notice intact and include a copy
+ * of the CONTRIB file.
+ *
+ * Binary distributions must follow the binary distribution requirements of
+ * either License.
+ */
+
+#ifndef LIBFREENECT_AUDIO_H
+#define LIBFREENECT_AUDIO_H
+
+#include <libfreenect.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Structure to represent a single 16-bit signed little-endian PCM sample.
+typedef struct {
+ int16_t left;
+ int16_t right;
+ int16_t center;
+ int16_t lfe;
+ int16_t surround_left;
+ int16_t surround_right;
+} freenect_sample_51;
+
+/**
+ * Typedef for "you wanted this microphone data, here it is" event callbacks.
+ * TODO: Timestamp details
+ * The format of the unknown stream is as of yet undetermined.
+ *
+ * @param dev Device which triggered this callback
+ * @param num_samples Number of samples provided in each of the audio data arrays (mic[1-4] and cancelled)
+ * @param mic1 Microphone data for the leftmost microphone: 32-bit PCM little-endian samples at 16kHz.
+ * @param mic2 Microphone data for the left-middle microphone: 32-bit PCM little-endian samples at 16kHz.
+ * @param mic3 Microphone data for the right-middle microphone: 32-bit PCM little-endian samples at 16kHz.
+ * @param mic4 Microphone data for the rightmost microphone: 32-bit PCM little-endian samples at 16kHz.
+ * @param cancelled Noise-cancelled audio data: 16-bit PCM little-endian samples at 16kHz.
+ */
+typedef void (*freenect_audio_in_cb)(freenect_device *dev, int num_samples,
+ int32_t* mic1, int32_t* mic2,
+ int32_t* mic3, int32_t* mic4,
+ int16_t* cancelled, void *unknown/*, timestamp_t timestamp*/);
+
+/**
+ * Typedef for "you're playing audio, the library needs you to fill up the outgoing audio buffer" event callbacks
+ * The library will request samples at a rate of 48000Hz.
+ *
+ * @param dev Device this callback was triggered for
+ * @param samples Pointer to the memory where the library expects you to copy the next sample_count freenect_sample_51's to.
+ * @param sample_count Bidirectional. in: maximum number of samples the driver wants (don't copy in more than this, you'll clobber memory). out: actual number of samples provided to the driver.
+ */
+typedef void (*freenect_audio_out_cb)(freenect_device *dev, freenect_sample_51* samples, int* sample_count);
+
+/**
+ * Set the audio in callback. This is the function called when the library
+ * has new microphone samples. It will be called approximately 62.5 times per
+ * second (16kHz sample rate, expect 512 samples/callback)
+ *
+ * @param dev Device for which to set the callback
+ * @param callback Callback function to set
+ */
+FREENECTAPI void freenect_set_audio_in_callback(freenect_device *dev, freenect_audio_in_cb callback);
+
+/**
+ * Set the audio out callback. This is the "tell me what audio you're about
+ * to play through the speakers so the Kinect can subtract it out" callback for
+ * a given device. If you choose not set an audio_out_callback, the library
+ * will send silence to the Kinect for you - it requires data either way.
+ *
+ * @param dev Device for which to set the callback
+ * @param callback Callback function to set
+ */
+FREENECTAPI void freenect_set_audio_out_callback(freenect_device *dev, freenect_audio_out_cb callback);
+
+/**
+ * Start streaming audio for the specified device.
+ *
+ * @param dev Device for which to start audio streaming
+ *
+ * @return 0 on success, < 0 if error
+ */
+FREENECTAPI int freenect_start_audio(freenect_device* dev);
+
+/**
+ * Stop streaming audio for the specified device.
+ *
+ * @param dev Device for which to stop audio streaming
+ *
+ * @return 0 on success, < 0 if error
+ */
+FREENECTAPI int freenect_stop_audio(freenect_device* dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //
+
+
View
@@ -517,85 +517,6 @@ FREENECTAPI const freenect_frame_mode freenect_find_depth_mode(freenect_resoluti
*/
FREENECTAPI int freenect_set_depth_mode(freenect_device* dev, const freenect_frame_mode mode);
-/* Audio API begins here. Audio is currently unsupported on Windows. Sorry. */
-
-/// Structure to represent a single 16-bit signed little-endian PCM sample.
-typedef struct {
- int16_t left;
- int16_t right;
- int16_t center;
- int16_t lfe;
- int16_t surround_left;
- int16_t surround_right;
-} freenect_sample_51;
-
-/**
- * Typedef for "you wanted this microphone data, here it is" event callbacks.
- * TODO: Timestamp details
- * The format of the unknown stream is as of yet undetermined.
- *
- * @param dev Device which triggered this callback
- * @param num_samples Number of samples provided in each of the audio data arrays (mic[1-4] and cancelled)
- * @param mic1 Microphone data for the leftmost microphone: 32-bit PCM little-endian samples at 16kHz.
- * @param mic2 Microphone data for the left-middle microphone: 32-bit PCM little-endian samples at 16kHz.
- * @param mic3 Microphone data for the right-middle microphone: 32-bit PCM little-endian samples at 16kHz.
- * @param mic4 Microphone data for the rightmost microphone: 32-bit PCM little-endian samples at 16kHz.
- * @param cancelled Noise-cancelled audio data: 16-bit PCM little-endian samples at 16kHz.
- */
-typedef void (*freenect_audio_in_cb)(freenect_device *dev, int num_samples,
- int32_t* mic1, int32_t* mic2,
- int32_t* mic3, int32_t* mic4,
- int16_t* cancelled, void *unknown/*, timestamp_t timestamp*/);
-
-/**
- * Typedef for "you're playing audio, the library needs you to fill up the outgoing audio buffer" event callbacks
- * The library will request samples at a rate of 48000Hz.
- *
- * @param dev Device this callback was triggered for
- * @param samples Pointer to the memory where the library expects you to copy the next sample_count freenect_sample_51's to.
- * @param sample_count Bidirectional. in: maximum number of samples the driver wants (don't copy in more than this, you'll clobber memory). out: actual number of samples provided to the driver.
- */
-typedef void (*freenect_audio_out_cb)(freenect_device *dev, freenect_sample_51* samples, int* sample_count);
-
-/**
- * Set the audio in callback. This is the function called when the library
- * has new microphone samples. It will be called approximately 62.5 times per
- * second (16kHz sample rate, expect 512 samples/callback)
- *
- * @param dev Device for which to set the callback
- * @param callback Callback function to set
- */
-FREENECTAPI void freenect_set_audio_in_callback(freenect_device *dev, freenect_audio_in_cb callback);
-
-/**
- * Set the audio out callback. This is the "tell me what audio you're about
- * to play through the speakers so the Kinect can subtract it out" callback for
- * a given device. If you choose not set an audio_out_callback, the library
- * will send silence to the Kinect for you - it requires data either way.
- *
- * @param dev Device for which to set the callback
- * @param callback Callback function to set
- */
-FREENECTAPI void freenect_set_audio_out_callback(freenect_device *dev, freenect_audio_out_cb callback);
-
-/**
- * Start streaming audio for the specified device.
- *
- * @param dev Device for which to start audio streaming
- *
- * @return 0 on success, < 0 if error
- */
-FREENECTAPI int freenect_start_audio(freenect_device* dev);
-
-/**
- * Stop streaming audio for the specified device.
- *
- * @param dev Device for which to stop audio streaming
- *
- * @return 0 on success, < 0 if error
- */
-FREENECTAPI int freenect_stop_audio(freenect_device* dev);
-
#ifdef __cplusplus
}
#endif
View
@@ -15,17 +15,17 @@ ELSE(WIN32)
ENDIF(WIN32)
IF(BUILD_AUDIO)
- LIST(APPEND SRC audio.c)
+ LIST(APPEND SRC audio.c loader.c)
IF(BUILD_REDIST_PACKAGE)
# If this build is intended for a redistributable package, we can't include audios.bin, so we should include fwfetcher.py
# and the package should run "python fwfetcher.py $INSTALL_PREFIX/share" as a postinst hook
- install (FILES "fwfetcher.py" DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}/share")
+ install (FILES "fwfetcher.py" DESTINATION "${CMAKE_INSTALL_PREFIX}/share")
ELSE(BUILD_REDIST_PACKAGE)
# If the install is local only, we can just run fwfetcher.py and install the audios.bin firmware to the system folder
add_custom_target(firmware ALL
COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/fwfetcher.py" "${CMAKE_CURRENT_BINARY_DIR}/audios.bin"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/fwfetcher.py")
- install (FILES "${CMAKE_CURRENT_BINARY_DIR}/audios.bin" DESTINATION "${PROJECT_LIBRARY_INSTALL_DIR}/share")
+ install (FILES "${CMAKE_CURRENT_BINARY_DIR}/audios.bin" DESTINATION "${CMAKE_INSTALL_PREFIX}/share")
ENDIF()
ENDIF()
@@ -47,9 +47,13 @@ install (TARGETS freenectstatic
target_link_libraries (freenect ${LIBUSB_1_LIBRARIES})
target_link_libraries (freenectstatic ${LIBUSB_1_LIBRARIES})
-# Install the header file
+# Install the header files
install (FILES "../include/libfreenect.h"
DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR})
+if(BUILD_AUDIO)
+ install (FILES "../include/libfreenect-audio.h"
+ DESTINATION ${PROJECT_INCLUDE_INSTALL_DIR})
+endif()
IF(UNIX AND NOT APPLE)
# Produce a pkg-config file for linking against the shared lib
View
@@ -24,6 +24,7 @@
* either License.
*/
#include "libfreenect.h"
+#include "libfreenect-audio.h"
#include "freenect_internal.h"
#include <string.h>
View
@@ -32,6 +32,9 @@
#include <unistd.h>
#include "freenect_internal.h"
+#ifdef BUILD_AUDIO
+#include "loader.h"
+#endif
FREENECTAPI int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx)
{
@@ -79,11 +82,35 @@ FREENECTAPI int freenect_open_device(freenect_context *ctx, freenect_device **de
pdev->parent = ctx;
res = fnusb_open_subdevices(pdev, index);
-
if (res < 0) {
free(pdev);
return res;
}
+#ifdef BUILD_AUDIO
+ res = fnusb_num_interfaces(&pdev->usb_audio);
+ if (res == 1) {
+ // Upload audio firmware, release devices, and reopen them
+ res = upload_firmware(&pdev->usb_audio);
+ if (res < 0) {
+ FN_ERROR("upload_firmware failed: %d\n", res);
+ free(pdev);
+ return res;
+ }
+
+ res = fnusb_close_subdevices(pdev);
+ if (res < 0) {
+ FN_ERROR("fnusb_close_subdevices failed: %d\n", res);
+ free(pdev);
+ return res;
+ }
+ sleep(1); // Give time for the device to reenumerate before trying to open it
+ res = fnusb_open_subdevices(pdev, index);
+ if (res < 0) {
+ free(pdev);
+ return res;
+ }
+ }
+#endif
if (!ctx->first) {
ctx->first = pdev;
View
@@ -31,6 +31,10 @@
#include "libfreenect.h"
+#ifdef BUILD_AUDIO
+#include "libfreenect-audio.h"
+#endif
+
typedef void (*fnusb_iso_cb)(freenect_device *dev, uint8_t *buf, int len);
#include "usb_libusb10.h"
@@ -194,7 +198,7 @@ struct _freenect_device {
freenect_audio_out_cb audio_out_cb;
audio_stream audio;
- uint16_t audio_tag;
+ uint32_t audio_tag;
#endif
// Motor
fnusb_dev usb_motor;
Oops, something went wrong.

0 comments on commit b886db0

Please sign in to comment.