overte-HifiExperiments/libraries/audio/src/AudioInjector.cpp
2013-06-13 11:11:59 -07:00

141 lines
4.8 KiB
C++

//
// AudioInjector.cpp
// hifi
//
// Created by Stephen Birarda on 4/23/13.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#include <fstream>
#include <cstring>
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <UDPSocket.h>
#include "AudioInjector.h"
AudioInjector::AudioInjector(const char* filename) :
_position(0.0f, 0.0f, 0.0f),
_orientation(0.0f, 0.0f, 0.0f, 0.0f),
_radius(0.0f),
_volume(MAX_INJECTOR_VOLUME),
_indexOfNextSlot(0),
_isInjectingAudio(false)
{
loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES);
std::fstream sourceFile;
sourceFile.open(filename, std::ios::in | std::ios::binary);
sourceFile.seekg(0, std::ios::end);
int totalBytes = sourceFile.tellg();
if (totalBytes == -1) {
printf("Error reading audio data from file %s\n", filename);
_audioSampleArray = NULL;
} else {
printf("Read %d bytes from audio file\n", totalBytes);
sourceFile.seekg(0, std::ios::beg);
_numTotalSamples = totalBytes / 2;
_audioSampleArray = new int16_t[_numTotalSamples];
sourceFile.read((char *)_audioSampleArray, totalBytes);
}
}
AudioInjector::AudioInjector(int maxNumSamples) :
_numTotalSamples(maxNumSamples),
_position(0.0f, 0.0f, 0.0f),
_orientation(0.0f, 0.0f, 0.0f, 0.0f),
_radius(0.0f),
_volume(MAX_INJECTOR_VOLUME),
_indexOfNextSlot(0),
_isInjectingAudio(false)
{
loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES);
_audioSampleArray = new int16_t[maxNumSamples];
memset(_audioSampleArray, 0, _numTotalSamples * sizeof(int16_t));
}
AudioInjector::~AudioInjector() {
delete[] _audioSampleArray;
}
void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destinationSocket) {
if (_audioSampleArray) {
_isInjectingAudio = true;
timeval startTime;
// calculate the number of bytes required for additional data
int leadingBytes = sizeof(PACKET_HEADER)
+ sizeof(_streamIdentifier)
+ sizeof(_position)
+ sizeof(_orientation)
+ sizeof(_radius)
+ sizeof(_volume);
unsigned char dataPacket[(BUFFER_LENGTH_SAMPLES_PER_CHANNEL * sizeof(int16_t)) + leadingBytes];
dataPacket[0] = PACKET_HEADER_INJECT_AUDIO;
unsigned char *currentPacketPtr = dataPacket + sizeof(PACKET_HEADER_INJECT_AUDIO);
// copy the identifier for this injector
memcpy(currentPacketPtr, &_streamIdentifier, sizeof(_streamIdentifier));
currentPacketPtr += sizeof(_streamIdentifier);
memcpy(currentPacketPtr, &_position, sizeof(_position));
currentPacketPtr += sizeof(_position);
memcpy(currentPacketPtr, &_orientation, sizeof(_orientation));
currentPacketPtr += sizeof(_orientation);
memcpy(currentPacketPtr, &_radius, sizeof(_radius));
currentPacketPtr += sizeof(_radius);
*currentPacketPtr = _volume;
currentPacketPtr++;
gettimeofday(&startTime, NULL);
int nextFrame = 0;
for (int i = 0; i < _numTotalSamples; i += BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
int numSamplesToCopy = BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
if (_numTotalSamples - i < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
numSamplesToCopy = _numTotalSamples - i;
memset(currentPacketPtr + numSamplesToCopy,
0,
BUFFER_LENGTH_BYTES_PER_CHANNEL - (numSamplesToCopy * sizeof(int16_t)));
}
memcpy(currentPacketPtr, _audioSampleArray + i, numSamplesToCopy * sizeof(int16_t));
injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket));
long long usecToSleep = usecTimestamp(&startTime) + (++nextFrame * INJECT_INTERVAL_USECS) - usecTimestampNow();
if (usecToSleep > 0) {
usleep(usecToSleep);
}
}
_isInjectingAudio = false;
}
}
void AudioInjector::addSample(const int16_t sample) {
if (_indexOfNextSlot != _numTotalSamples) {
// only add this sample if we actually have space for it
_audioSampleArray[_indexOfNextSlot++] = sample;
}
}
void AudioInjector::addSamples(int16_t* sampleBuffer, int numSamples) {
if (_audioSampleArray + _indexOfNextSlot + numSamples <= _audioSampleArray + (_numTotalSamples / sizeof(int16_t))) {
// only copy the audio from the sample buffer if there's space
memcpy(_audioSampleArray + _indexOfNextSlot, sampleBuffer, numSamples * sizeof(int16_t));
_indexOfNextSlot += numSamples;
}
}