Merge remote-tracking branch 'origin/master'

This commit is contained in:
Philip Rosedale 2013-02-12 01:52:23 -08:00
commit b651032b06
9 changed files with 338 additions and 33 deletions

View file

@ -0,0 +1,82 @@
# - Try to find jack-2.6
# Once done this will define
#
# JACK_FOUND - system has jack
# JACK_INCLUDE_DIRS - the jack include directory
# JACK_LIBRARIES - Link these to use jack
# JACK_DEFINITIONS - Compiler switches required for using jack
#
# Copyright (c) 2008 Andreas Schneider <mail@cynapses.org>
# Modified for other libraries by Lasse Kärkkäinen <tronic>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)
# in cache already
set(JACK_FOUND TRUE)
else (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
include(UsePkgConfig)
pkgconfig(jack _JACK_INCLUDEDIR _JACK_LIBDIR _JACK_LDFLAGS _JACK_CFLAGS)
else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_JACK jack)
endif (PKG_CONFIG_FOUND)
endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
find_path(JACK_INCLUDE_DIR
NAMES
jack/jack.h
PATHS
${_JACK_INCLUDEDIR}
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
find_library(JACK_LIBRARY
NAMES
jack
PATHS
${_JACK_LIBDIR}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
if (JACK_LIBRARY AND JACK_INCLUDE_DIR)
set(JACK_FOUND TRUE)
set(JACK_INCLUDE_DIRS
${JACK_INCLUDE_DIR}
)
set(JACK_LIBRARIES
${JACK_LIBRARIES}
${JACK_LIBRARY}
)
endif (JACK_LIBRARY AND JACK_INCLUDE_DIR)
if (JACK_FOUND)
if (NOT JACK_FIND_QUIETLY)
message(STATUS "Found jack: ${JACK_LIBRARY}")
endif (NOT JACK_FIND_QUIETLY)
else (JACK_FOUND)
if (JACK_FIND_REQUIRED)
message(FATAL_ERROR "Could not find JACK")
endif (JACK_FIND_REQUIRED)
endif (JACK_FOUND)
# show the JACK_INCLUDE_DIRS and JACK_LIBRARIES variables only in the advanced view
mark_as_advanced(JACK_INCLUDE_DIRS JACK_LIBRARIES)
endif (JACK_LIBRARIES AND JACK_INCLUDE_DIRS)

View file

@ -0,0 +1,61 @@
# You may redistribute this program and/or modify it under the terms of
# the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
if(NOT LIBRT_FOUND)
find_path(LIBRT_INCLUDE_DIR
NAMES
time.h
PATHS
${LIBRTDIR}/include/
)
find_file(
LIBRT_LIBRARIES librt.a
PATHS
${LIBRTDIR}/lib/
/usr/local/lib64/
/usr/local/lib/
/usr/lib/i386-linux-gnu/
/usr/lib/x86_64-linux-gnu/
/usr/lib64/
/usr/lib/
)
set (LIBRT_DYNAMIC "Using static library.")
if (NOT LIBRT_LIBRARIES)
find_library(
LIBRT_LIBRARIES rt
PATHS
${LIBRTDIR}/lib/
/usr/local/lib64/
/usr/local/lib/
/usr/lib/i386-linux-gnu/
/usr/lib/x86_64-linux-gnu/
/usr/lib64/
/usr/lib/
)
set (LIBRT_DYNAMIC "Using dynamic library.")
endif (NOT LIBRT_LIBRARIES)
if (LIBRT_INCLUDE_DIR AND LIBRT_LIBRARIES)
set (LIBRT_FOUND TRUE)
endif (LIBRT_INCLUDE_DIR AND LIBRT_LIBRARIES)
if (LIBRT_FOUND)
message(STATUS "Found librt: ${LIBRT_INCLUDE_DIR}, ${LIBRT_LIBRARIES} ${LIBRT_DYNAMIC}")
else (LIBRT_FOUND)
if (Librt_FIND_REQUIRED)
message (FATAL_ERROR "Could not find librt, try to setup LIBRT_PREFIX accordingly")
endif (Librt_FIND_REQUIRED)
endif (LIBRT_FOUND)
endif (NOT LIBRT_FOUND)

View file

@ -35,14 +35,30 @@ target_link_libraries(interface
)
include(ExternalProject)
set(PORTAUDIO_PROJ_DIR external/portaudio)
ExternalProject_Add(
portaudio
PREFIX external/portaudio
PREFIX ${PORTAUDIO_PROJ_DIR}
BINARY_DIR ${PORTAUDIO_PROJ_DIR}/src/portaudio
URL ${PORTAUDIO_DIR}/pa_snapshot_020813.tgz
CONFIGURE_COMMAND <SOURCE_DIR>/configure
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix "${CMAKE_CURRENT_SOURCE_DIR}/${PORTAUDIO_PROJ_DIR}"
BUILD_COMMAND make
)
if (UNIX AND NOT APPLE)
find_package(Threads REQUIRED)
find_package(Librt REQUIRED)
find_package(Jack REQUIRED)
find_package(ALSA REQUIRED)
target_link_libraries(portaudio
${CMAKE_THREAD_LIBS_INIT}
${LIBRT_LIBRARIES}
${JACK_LIBRARIES}
${ALSA_LIBRARIES}
)
endif (UNIX AND NOT APPLE)
ExternalProject_Get_Property(portaudio binary_dir)
ExternalProject_Get_Property(portaudio source_dir)
include_directories(${source_dir}/include)

View file

@ -39,6 +39,7 @@ AudioData::~AudioData() {
}
}
delete[] samplesToQueue;
delete audioSocket;
}

View file

@ -17,6 +17,7 @@
class UDPSocket {
public:
UDPSocket(int listening_port);
~UDPSocket();
int send(char *destAddress, int destPort, const void *data, int byteLength);
bool receive(void *receivedData, int *receivedBytes);
bool receive(sockaddr_in *senderAddress, void *receivedData, int *receivedBytes);

View file

@ -611,14 +611,13 @@ void display(void)
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
//lattice.render(WIDTH, HEIGHT);
// lattice.render(WIDTH, HEIGHT);
// myFinger.render();
Audio::render(WIDTH, HEIGHT);
//drawvec3(100, 100, 0.15, 0, 1.0, 0, myHead.getPos(), 0, 1, 0);
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, pointer_attenuation_quadratic );
// myFinger.render();
if (mouse_pressed == 1)
{
glPointSize( 10.0f );
@ -868,7 +867,7 @@ void mouseFunc( int button, int state, int x, int y )
mouse_x = x;
mouse_y = y;
mouse_pressed = 1;
// lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
}
if( button == GLUT_LEFT_BUTTON && state == GLUT_UP )
{
@ -901,8 +900,8 @@ void mouseoverFunc( int x, int y)
mouse_y = y;
if (mouse_pressed == 0)
{
lattice.mouseOver((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
myFinger.setTarget(mouse_x, mouse_y);
// lattice.mouseOver((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
// myFinger.setTarget(mouse_x, mouse_y);
}
}

View file

@ -0,0 +1,51 @@
//
// AudioRingBuffer.cpp
// interface
//
// Created by Stephen Birarda on 2/1/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#include "AudioRingBuffer.h"
AudioRingBuffer::AudioRingBuffer(short ringBufferSamples) {
ringBufferLengthSamples = ringBufferSamples;
started = false;
transmitted = false;
endOfLastWrite = NULL;
buffer = new int16_t[ringBufferLengthSamples];
nextOutput = buffer;
};
AudioRingBuffer::~AudioRingBuffer() {
delete[] buffer;
};
short AudioRingBuffer::diffLastWriteNextOutput()
{
if (endOfLastWrite == NULL) {
return 0;
} else {
short sampleDifference = endOfLastWrite - nextOutput;
if (sampleDifference < 0) {
sampleDifference += ringBufferLengthSamples;
}
return sampleDifference;
}
}
short AudioRingBuffer::bufferOverlap(int16_t *pointer, short addedDistance)
{
short samplesLeft = (buffer + ringBufferLengthSamples) - pointer;
if (samplesLeft < addedDistance) {
return addedDistance - samplesLeft;
} else {
return 0;
}
}

View file

@ -0,0 +1,31 @@
//
// AudioRingBuffer.h
// interface
//
// Created by Stephen Birarda on 2/1/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#ifndef __interface__AudioRingBuffer__
#define __interface__AudioRingBuffer__
#include <iostream>
#include <stdint.h>
class AudioRingBuffer {
public:
int16_t *nextOutput;
int16_t *endOfLastWrite;
int16_t *buffer;
short ringBufferLengthSamples;
bool started;
bool transmitted;
short diffLastWriteNextOutput();
short bufferOverlap(int16_t *pointer, short addedDistance);
AudioRingBuffer(short ringBufferSamples);
~AudioRingBuffer();
};
#endif /* defined(__interface__AudioRingBuffer__) */

View file

@ -12,6 +12,7 @@
#include <errno.h>
#include <fstream>
#include <limits>
#include "AudioRingBuffer.h"
const int MAX_AGENTS = 1000;
const int LOGOFF_CHECK_INTERVAL = 1000;
@ -23,10 +24,16 @@ const int BUFFER_LENGTH_SAMPLES = BUFFER_LENGTH_BYTES / sizeof(int16_t);
const float SAMPLE_RATE = 22050.0;
const float BUFFER_SEND_INTERVAL_USECS = (BUFFER_LENGTH_SAMPLES/SAMPLE_RATE) * 1000000;
const int MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
const short JITTER_BUFFER_MSECS = 20;
const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_MSECS * (SAMPLE_RATE / 1000.0);
const int MAX_SOURCE_BUFFERS = 10;
const short RING_BUFFER_FRAMES = 10;
const short RING_BUFFER_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES;
const long MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
const long MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
const int MAX_SOURCE_BUFFERS = 20;
int16_t* whiteNoiseBuffer;
int whiteNoiseLength;
@ -44,10 +51,7 @@ struct AgentList {
int num_agents = 0;
struct SourceBuffer {
int16_t sourceAudioData[BUFFER_LENGTH_SAMPLES];
bool transmitted;
} sourceBuffers[MAX_SOURCE_BUFFERS];
AudioRingBuffer *sourceBuffers[MAX_SOURCE_BUFFERS];
double diffclock(timeval *clock1, timeval *clock2)
{
@ -110,8 +114,22 @@ int addAgent(sockaddr_in dest_address, void *audioData) {
agents[i].active = true;
gettimeofday(&agents[i].time, NULL);
memcpy(sourceBuffers[i].sourceAudioData, audioData, BUFFER_LENGTH_BYTES);
sourceBuffers[i].transmitted = false;
if (sourceBuffers[i]->endOfLastWrite == NULL) {
sourceBuffers[i]->endOfLastWrite = sourceBuffers[i]->buffer;
} else if (sourceBuffers[i]->diffLastWriteNextOutput() > RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES) {
// reset us to started state
sourceBuffers[i]->endOfLastWrite = sourceBuffers[i]->buffer;
sourceBuffers[i]->nextOutput = sourceBuffers[i]->buffer;
sourceBuffers[i]->started = false;
}
memcpy(sourceBuffers[i]->endOfLastWrite, audioData, BUFFER_LENGTH_BYTES);
sourceBuffers[i]->endOfLastWrite += BUFFER_LENGTH_SAMPLES;
if (sourceBuffers[i]->endOfLastWrite >= sourceBuffers[i]->buffer + RING_BUFFER_SAMPLES) {
sourceBuffers[i]->endOfLastWrite = sourceBuffers[i]->buffer;
}
if (i == num_agents) {
num_agents++;
@ -134,7 +152,7 @@ void *send_buffer_thread(void *args)
timeval startTime, sendTime, now;
int16_t *clientMix = new int16_t[BUFFER_LENGTH_SAMPLES];
int16_t *masterMix = new int16_t[BUFFER_LENGTH_SAMPLES];
long *masterMix = new long[BUFFER_LENGTH_SAMPLES];
gettimeofday(&startTime, NULL);
@ -142,28 +160,73 @@ void *send_buffer_thread(void *args)
sentBytes = 0;
int sampleOffset = ((currentFrame - 1) * BUFFER_LENGTH_SAMPLES) % whiteNoiseLength;
memcpy(masterMix, whiteNoiseBuffer + sampleOffset, BUFFER_LENGTH_BYTES);
int16_t *noisePointer = whiteNoiseBuffer + sampleOffset;
for (int wb = 0; wb < BUFFER_LENGTH_SAMPLES; wb++) {
masterMix[wb] = noisePointer[wb];
}
gettimeofday(&sendTime, NULL);
for (int b = 0; b < MAX_SOURCE_BUFFERS; b++) {
if (sourceBuffers[b]->endOfLastWrite != NULL) {
if (!sourceBuffers[b]->started
&& sourceBuffers[b]->diffLastWriteNextOutput() <= BUFFER_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) {
std::cout << "Held back buffer " << b << ".\n";
} else if (sourceBuffers[b]->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES) {
std::cout << "Buffer " << b << " starved.\n";
sourceBuffers[b]->started = false;
} else {
sourceBuffers[b]->started = true;
sourceBuffers[b]->transmitted = true;
for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) {
masterMix[s] += sourceBuffers[b]->nextOutput[s];
}
sourceBuffers[b]->nextOutput += BUFFER_LENGTH_SAMPLES;
if (sourceBuffers[b]->nextOutput >= sourceBuffers[b]->buffer + RING_BUFFER_SAMPLES) {
sourceBuffers[b]->nextOutput = sourceBuffers[b]->buffer;
}
}
}
}
for (int a = 0; a < num_agents; a++) {
if (diffclock(&agents[a].time, &sendTime) <= LOGOFF_CHECK_INTERVAL) {
memcpy(clientMix, masterMix, BUFFER_LENGTH_BYTES);
int16_t *previousOutput = NULL;
if (sourceBuffers[a]->transmitted) {
previousOutput = (sourceBuffers[a]->nextOutput == sourceBuffers[a]->buffer)
? sourceBuffers[a]->buffer + RING_BUFFER_SAMPLES - BUFFER_LENGTH_SAMPLES
: sourceBuffers[a]->nextOutput - BUFFER_LENGTH_SAMPLES;
sourceBuffers[a]->transmitted = false;
}
for (int b = 0; b < MAX_SOURCE_BUFFERS; b++) {
if (b != a && !sourceBuffers[b].transmitted) {
for (int s = 0; s < BUFFER_LENGTH_SAMPLES; s++) {
// we have source buffer data for this sample
int mixSample = clientMix[s] + sourceBuffers[b].sourceAudioData[s];
int sampleToAdd = std::max(mixSample, MIN_SAMPLE_VALUE);
sampleToAdd = std::min(sampleToAdd, MAX_SAMPLE_VALUE);
for(int as = 0; as < BUFFER_LENGTH_SAMPLES; as++) {
long longSample = previousOutput != NULL
? masterMix[as] - previousOutput[as]
: masterMix[as];
clientMix[s] = sampleToAdd;
}
int16_t shortSample;
if (longSample < 0) {
shortSample = std::max(longSample, MIN_SAMPLE_VALUE);
} else {
shortSample = std::min(longSample, MAX_SAMPLE_VALUE);
}
sourceBuffers[b].transmitted = true;
clientMix[as] = shortSample;
// std::cout << as << " - CM: " << clientMix[as] << " MM: " << masterMix[as] << "\n";
// std::cout << previousOutput - sourceBuffers[a]->buffer << "\n";
if (previousOutput != NULL) {
// std::cout << "PO: " << previousOutput[as] << "\n";
}
}
sockaddr_in dest_address = agents[a].agent_addr;
@ -259,7 +322,7 @@ int main(int argc, const char * argv[])
int16_t packet_data[BUFFER_LENGTH_SAMPLES];
for (int b = 0; b < MAX_SOURCE_BUFFERS; b++) {
sourceBuffers[b].transmitted = true;
sourceBuffers[b] = new AudioRingBuffer(10 * BUFFER_LENGTH_SAMPLES);
}
struct send_buffer_struct send_buffer_args;