blob: 8f0061faae7a80ec22a84edccd1085875b742e7a [file] [log] [blame]
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "voe_file_impl.h"
#include "channel.h"
#include "critical_section_wrapper.h"
#include "file_wrapper.h"
#include "media_file.h"
#include "output_mixer.h"
#include "trace.h"
#include "transmit_mixer.h"
#include "voe_errors.h"
#include "voice_engine_impl.h"
namespace webrtc {
VoEFile* VoEFile::GetInterface(VoiceEngine* voiceEngine)
{
#ifndef WEBRTC_VOICE_ENGINE_FILE_API
return NULL;
#else
if (NULL == voiceEngine)
{
return NULL;
}
VoiceEngineImpl* s = reinterpret_cast<VoiceEngineImpl*>(voiceEngine);
s->AddRef();
return s;
#endif
}
#ifdef WEBRTC_VOICE_ENGINE_FILE_API
VoEFileImpl::VoEFileImpl(voe::SharedData* shared) : _shared(shared)
{
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
"VoEFileImpl::VoEFileImpl() - ctor");
}
VoEFileImpl::~VoEFileImpl()
{
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
"VoEFileImpl::~VoEFileImpl() - dtor");
}
int VoEFileImpl::StartPlayingFileLocally(
int channel,
const char fileNameUTF8[1024],
bool loop, FileFormats format,
float volumeScaling,
int startPointMs,
int stopPointMs)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartPlayingFileLocally(channel=%d, fileNameUTF8[]=%s, "
"loop=%d, format=%d, volumeScaling=%5.3f, startPointMs=%d,"
" stopPointMs=%d)",
channel, fileNameUTF8, loop, format, volumeScaling,
startPointMs, stopPointMs);
assert(1024 == FileWrapper::kMaxFileNameSize);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->StartPlayingFileLocally(fileNameUTF8,
loop,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
}
int VoEFileImpl::StartPlayingFileLocally(int channel,
InStream* stream,
FileFormats format,
float volumeScaling,
int startPointMs,
int stopPointMs)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartPlayingFileLocally(channel=%d, stream, format=%d, "
"volumeScaling=%5.3f, startPointMs=%d, stopPointMs=%d)",
channel, format, volumeScaling, startPointMs, stopPointMs);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->StartPlayingFileLocally(stream,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
}
int VoEFileImpl::StopPlayingFileLocally(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StopPlayingFileLocally()");
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->StopPlayingFileLocally();
}
int VoEFileImpl::IsPlayingFileLocally(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"IsPlayingFileLocally(channel=%d)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->IsPlayingFileLocally();
}
int VoEFileImpl::ScaleLocalFilePlayout(int channel, float scale)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ScaleLocalFilePlayout(channel=%d, scale=%5.3f)",
channel, scale);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopPlayingFileLocally() failed to locate channel");
return -1;
}
return channelPtr->ScaleLocalFilePlayout(scale);
}
int VoEFileImpl::StartPlayingFileAsMicrophone(int channel,
const char fileNameUTF8[1024],
bool loop,
bool mixWithMicrophone,
FileFormats format,
float volumeScaling)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone(channel=%d, fileNameUTF8=%s, "
"loop=%d, mixWithMicrophone=%d, format=%d, "
"volumeScaling=%5.3f)",
channel, fileNameUTF8, loop, mixWithMicrophone, format,
volumeScaling);
assert(1024 == FileWrapper::kMaxFileNameSize);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
const WebRtc_UWord32 startPointMs(0);
const WebRtc_UWord32 stopPointMs(0);
if (channel == -1)
{
int res = _shared->transmit_mixer()->StartPlayingFileAsMicrophone(
fileNameUTF8,
loop,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
if (res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone() failed to start playing file");
return(-1);
}
else
{
_shared->transmit_mixer()->SetMixWithMicStatus(mixWithMicrophone);
return(0);
}
}
else
{
// Add file after demultiplexing <=> affects one channel only
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
int res = channelPtr->StartPlayingFileAsMicrophone(fileNameUTF8,
loop,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
if (res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone() failed to start playing file");
return -1;
}
else
{
channelPtr->SetMixWithMicStatus(mixWithMicrophone);
return 0;
}
}
}
int VoEFileImpl::StartPlayingFileAsMicrophone(int channel,
InStream* stream,
bool mixWithMicrophone,
FileFormats format,
float volumeScaling)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone(channel=%d, stream,"
" mixWithMicrophone=%d, format=%d, volumeScaling=%5.3f)",
channel, mixWithMicrophone, format, volumeScaling);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
const WebRtc_UWord32 startPointMs(0);
const WebRtc_UWord32 stopPointMs(0);
if (channel == -1)
{
int res = _shared->transmit_mixer()->StartPlayingFileAsMicrophone(
stream,
format,
startPointMs,
volumeScaling,
stopPointMs,
NULL);
if (res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone() failed to start "
"playing stream");
return(-1);
}
else
{
_shared->transmit_mixer()->SetMixWithMicStatus(mixWithMicrophone);
return(0);
}
}
else
{
// Add file after demultiplexing <=> affects one channel only
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
int res = channelPtr->StartPlayingFileAsMicrophone(
stream, format, startPointMs, volumeScaling, stopPointMs, NULL);
if (res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartPlayingFileAsMicrophone() failed to start "
"playing stream");
return -1;
}
else
{
channelPtr->SetMixWithMicStatus(mixWithMicrophone);
return 0;
}
}
}
int VoEFileImpl::StopPlayingFileAsMicrophone(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StopPlayingFileAsMicrophone(channel=%d)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
// Stop adding file before demultiplexing <=> affects all channels
return _shared->transmit_mixer()->StopPlayingFileAsMicrophone();
}
else
{
// Stop adding file after demultiplexing <=> affects one channel only
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
return channelPtr->StopPlayingFileAsMicrophone();
}
}
int VoEFileImpl::IsPlayingFileAsMicrophone(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"IsPlayingFileAsMicrophone(channel=%d)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->transmit_mixer()->IsPlayingFileAsMicrophone();
}
else
{
// Stop adding file after demultiplexing <=> affects one channel only
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"IsPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
return channelPtr->IsPlayingFileAsMicrophone();
}
}
int VoEFileImpl::ScaleFileAsMicrophonePlayout(int channel, float scale)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ScaleFileAsMicrophonePlayout(channel=%d, scale=%5.3f)",
channel, scale);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->transmit_mixer()->ScaleFileAsMicrophonePlayout(scale);
}
else
{
// Stop adding file after demultiplexing <=> affects one channel only
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"IsPlayingFileAsMicrophone() failed to locate channel");
return -1;
}
return channelPtr->ScaleFileAsMicrophonePlayout(scale);
}
}
int VoEFileImpl::StartRecordingPlayout(
int channel, const char* fileNameUTF8, CodecInst* compression,
int maxSizeBytes)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartRecordingPlayout(channel=%d, fileNameUTF8=%s, "
"compression, maxSizeBytes=%d)",
channel, fileNameUTF8, maxSizeBytes);
assert(1024 == FileWrapper::kMaxFileNameSize);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->output_mixer()->StartRecordingPlayout
(fileNameUTF8, compression);
}
else
{
// Add file after demultiplexing <=> affects one channel only
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartRecordingPlayout() failed to locate channel");
return -1;
}
return channelPtr->StartRecordingPlayout(fileNameUTF8, compression);
}
}
int VoEFileImpl::StartRecordingPlayout(
int channel, OutStream* stream, CodecInst* compression)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartRecordingPlayout(channel=%d, stream, compression)",
channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->output_mixer()->
StartRecordingPlayout(stream, compression);
}
else
{
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StartRecordingPlayout() failed to locate channel");
return -1;
}
return channelPtr->StartRecordingPlayout(stream, compression);
}
}
int VoEFileImpl::StopRecordingPlayout(int channel)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StopRecordingPlayout(channel=%d)", channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (channel == -1)
{
return _shared->output_mixer()->StopRecordingPlayout();
}
else
{
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"StopRecordingPlayout() failed to locate channel");
return -1;
}
return channelPtr->StopRecordingPlayout();
}
}
int VoEFileImpl::StartRecordingMicrophone(
const char* fileNameUTF8, CodecInst* compression, int maxSizeBytes)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone(fileNameUTF8=%s, compression, "
"maxSizeBytes=%d)", fileNameUTF8, maxSizeBytes);
assert(1024 == FileWrapper::kMaxFileNameSize);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (_shared->transmit_mixer()->StartRecordingMicrophone(fileNameUTF8,
compression))
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to start recording");
return -1;
}
if (_shared->audio_device()->Recording())
{
return 0;
}
if (!_shared->ext_recording())
{
if (_shared->audio_device()->InitRecording() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to initialize recording");
return -1;
}
if (_shared->audio_device()->StartRecording() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to start recording");
return -1;
}
}
return 0;
}
int VoEFileImpl::StartRecordingMicrophone(
OutStream* stream, CodecInst* compression)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone(stream, compression)");
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (_shared->transmit_mixer()->StartRecordingMicrophone(stream,
compression) == -1)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to start recording");
return -1;
}
if (_shared->audio_device()->Recording())
{
return 0;
}
if (!_shared->ext_recording())
{
if (_shared->audio_device()->InitRecording() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to initialize recording");
return -1;
}
if (_shared->audio_device()->StartRecording() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StartRecordingMicrophone() failed to start recording");
return -1;
}
}
return 0;
}
int VoEFileImpl::StopRecordingMicrophone()
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"StopRecordingMicrophone()");
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
int err = 0;
// TODO(xians): consider removing Start/StopRecording() in
// Start/StopRecordingMicrophone() if no channel is recording.
if (_shared->NumOfSendingChannels() == 0 &&
_shared->audio_device()->Recording())
{
// Stop audio-device recording if no channel is recording
if (_shared->audio_device()->StopRecording() != 0)
{
_shared->SetLastError(VE_CANNOT_STOP_RECORDING, kTraceError,
"StopRecordingMicrophone() failed to stop recording");
err = -1;
}
}
if (_shared->transmit_mixer()->StopRecordingMicrophone() != 0)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"StopRecordingMicrophone() failed to stop recording to mixer");
err = -1;
}
return err;
}
// TODO(andrew): a cursory inspection suggests there's a large amount of
// overlap in these convert functions which could be refactored to a helper.
int VoEFileImpl::ConvertPCMToWAV(const char* fileNameInUTF8,
const char* fileNameOutUTF8)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ConvertPCMToWAV(fileNameInUTF8=%s, fileNameOutUTF8=%s)",
fileNameInUTF8, fileNameOutUTF8);
// Create file player object
FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
-1,
kFileFormatPcm16kHzFile));
int res=playerObj.StartPlayingFile(fileNameInUTF8,false,0,1.0,0,0, NULL);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertPCMToWAV failed to create player object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
return -1;
}
// Create file recorder object
FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
-1, kFileFormatWavFile));
CodecInst codecInst;
strncpy(codecInst.plname,"L16",32);
codecInst.channels = 1;
codecInst.rate = 256000;
codecInst.plfreq = 16000;
codecInst.pltype = 94;
codecInst.pacsize = 160;
res = recObj.StartRecordingAudioFile(fileNameOutUTF8,codecInst,0);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertPCMToWAV failed to create recorder object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
recObj.StopRecording();
FileRecorder::DestroyFileRecorder(&recObj);
return -1;
}
// Run throught the file
AudioFrame audioFrame;
WebRtc_Word16 decodedData[160];
int decLength=0;
const WebRtc_UWord32 frequency = 16000;
while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
{
if(decLength!=frequency/100)
{
// This is an OK way to end
break;
}
res=audioFrame.UpdateFrame(-1, 0, decodedData,
(WebRtc_UWord16)decLength,
frequency, AudioFrame::kNormalSpeech,
AudioFrame::kVadActive);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertPCMToWAV failed during conversion (audio frame)");
break;
}
res=recObj.RecordAudioToFile(audioFrame);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertPCMToWAV failed during conversion (write frame)");
}
}
playerObj.StopPlayingFile();
recObj.StopRecording();
FilePlayer::DestroyFilePlayer(&playerObj);
FileRecorder::DestroyFileRecorder(&recObj);
return res;
}
int VoEFileImpl::ConvertPCMToWAV(InStream* streamIn, OutStream* streamOut)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ConvertPCMToWAV(streamIn, streamOut)");
if ((streamIn == NULL) || (streamOut == NULL))
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1), "invalid stream handles");
return (-1);
}
// Create file player object
FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(-1,
kFileFormatPcm16kHzFile));
int res = playerObj.StartPlayingFile(*streamIn,0,1.0,0,0,NULL);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertPCMToWAV failed to create player object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
return -1;
}
// Create file recorder object
FileRecorder& recObj(*FileRecorder::CreateFileRecorder(-1,
kFileFormatWavFile));
CodecInst codecInst;
strncpy(codecInst.plname, "L16", 32);
codecInst.channels = 1;
codecInst.rate = 256000;
codecInst.plfreq = 16000;
codecInst.pltype = 94;
codecInst.pacsize = 160;
res = recObj.StartRecordingAudioFile(*streamOut,codecInst,0);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertPCMToWAV failed to create recorder object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
recObj.StopRecording();
FileRecorder::DestroyFileRecorder(&recObj);
return -1;
}
// Run throught the file
AudioFrame audioFrame;
WebRtc_Word16 decodedData[160];
int decLength=0;
const WebRtc_UWord32 frequency = 16000;
while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
{
if(decLength!=frequency/100)
{
// This is an OK way to end
break;
}
res=audioFrame.UpdateFrame(-1, 0, decodedData,
(WebRtc_UWord16)decLength, frequency,
AudioFrame::kNormalSpeech,
AudioFrame::kVadActive);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertPCMToWAV failed during conversion "
"(create audio frame)");
break;
}
res=recObj.RecordAudioToFile(audioFrame);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertPCMToWAV failed during conversion (write frame)");
}
}
playerObj.StopPlayingFile();
recObj.StopRecording();
FilePlayer::DestroyFilePlayer(&playerObj);
FileRecorder::DestroyFileRecorder(&recObj);
return res;
}
int VoEFileImpl::ConvertWAVToPCM(const char* fileNameInUTF8,
const char* fileNameOutUTF8)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ConvertWAVToPCM(fileNameInUTF8=%s, fileNameOutUTF8=%s)",
fileNameInUTF8, fileNameOutUTF8);
// Create file player object
FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(-1,
kFileFormatWavFile));
int res = playerObj.StartPlayingFile(fileNameInUTF8,false,0,1.0,0,0,NULL);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertWAVToPCM failed to create player object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
return -1;
}
// Create file recorder object
FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
-1, kFileFormatPcm16kHzFile));
CodecInst codecInst;
strncpy(codecInst.plname,"L16",32);
codecInst.channels = 1;
codecInst.rate = 256000;
codecInst.plfreq = 16000;
codecInst.pltype = 94;
codecInst.pacsize = 160;
res = recObj.StartRecordingAudioFile(fileNameOutUTF8,codecInst,0);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertWAVToPCM failed to create recorder object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
recObj.StopRecording();
FileRecorder::DestroyFileRecorder(&recObj);
return -1;
}
// Run throught the file
AudioFrame audioFrame;
WebRtc_Word16 decodedData[160];
int decLength=0;
const WebRtc_UWord32 frequency = 16000;
while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
{
if(decLength!=frequency/100)
{
// This is an OK way to end
break;
}
res=audioFrame.UpdateFrame(-1, 0, decodedData,
(WebRtc_UWord16)decLength,
frequency, AudioFrame::kNormalSpeech,
AudioFrame::kVadActive);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertWAVToPCM failed during conversion (audio frame)");
break;
}
res=recObj.RecordAudioToFile(audioFrame);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertWAVToPCM failed during conversion (write frame)");
}
}
playerObj.StopPlayingFile();
recObj.StopRecording();
FilePlayer::DestroyFilePlayer(&playerObj);
FileRecorder::DestroyFileRecorder(&recObj);
return res;
}
int VoEFileImpl::ConvertWAVToPCM(InStream* streamIn, OutStream* streamOut)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ConvertWAVToPCM(streamIn, streamOut)");
if ((streamIn == NULL) || (streamOut == NULL))
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1), "invalid stream handles");
return (-1);
}
// Create file player object
FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(-1,
kFileFormatWavFile));
int res = playerObj.StartPlayingFile(*streamIn,0,1.0,0,0,NULL);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertWAVToPCM failed to create player object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
return -1;
}
// Create file recorder object
FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
-1, kFileFormatPcm16kHzFile));
CodecInst codecInst;
strncpy(codecInst.plname,"L16",32);
codecInst.channels = 1;
codecInst.rate = 256000;
codecInst.plfreq = 16000;
codecInst.pltype = 94;
codecInst.pacsize = 160;
res = recObj.StartRecordingAudioFile(*streamOut,codecInst,0);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertWAVToPCM failed to create recorder object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
recObj.StopRecording();
FileRecorder::DestroyFileRecorder(&recObj);
return -1;
}
// Run throught the file
AudioFrame audioFrame;
WebRtc_Word16 decodedData[160];
int decLength=0;
const WebRtc_UWord32 frequency = 16000;
while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
{
if(decLength!=frequency/100)
{
// This is an OK way to end
break;
}
res=audioFrame.UpdateFrame(-1, 0, decodedData,
(WebRtc_UWord16)decLength, frequency,
AudioFrame::kNormalSpeech,
AudioFrame::kVadActive);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertWAVToPCM failed during conversion (audio frame)");
break;
}
res=recObj.RecordAudioToFile(audioFrame);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertWAVToPCM failed during conversion (write frame)");
}
}
playerObj.StopPlayingFile();
recObj.StopRecording();
FilePlayer::DestroyFilePlayer(&playerObj);
FileRecorder::DestroyFileRecorder(&recObj);
return res;
}
int VoEFileImpl::ConvertPCMToCompressed(const char* fileNameInUTF8,
const char* fileNameOutUTF8,
CodecInst* compression)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ConvertPCMToCompressed(fileNameInUTF8=%s, fileNameOutUTF8=%s"
", compression)", fileNameInUTF8, fileNameOutUTF8);
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
" compression: plname=%s, plfreq=%d, pacsize=%d",
compression->plname, compression->plfreq,
compression->pacsize);
// Create file player object
FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
-1,
kFileFormatPcm16kHzFile));
int res = playerObj.StartPlayingFile(fileNameInUTF8,false,0,1.0,0,0, NULL);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertPCMToCompressed failed to create player object");
// Clean up and shutdown the file player
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
return -1;
}
// Create file recorder object
FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
-1,
kFileFormatCompressedFile));
res = recObj.StartRecordingAudioFile(fileNameOutUTF8, *compression,0);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertPCMToCompressed failed to create recorder object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
recObj.StopRecording();
FileRecorder::DestroyFileRecorder(&recObj);
return -1;
}
// Run throught the file
AudioFrame audioFrame;
WebRtc_Word16 decodedData[160];
int decLength=0;
const WebRtc_UWord32 frequency = 16000;
while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
{
if(decLength!=frequency/100)
{
// This is an OK way to end
break;
}
res=audioFrame.UpdateFrame(-1, 0, decodedData,
(WebRtc_UWord16)decLength,
frequency, AudioFrame::kNormalSpeech,
AudioFrame::kVadActive);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertPCMToCompressed failed during conversion "
"(audio frame)");
break;
}
res=recObj.RecordAudioToFile(audioFrame);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertPCMToCompressed failed during conversion "
"(write frame)");
}
}
playerObj.StopPlayingFile();
recObj.StopRecording();
FilePlayer::DestroyFilePlayer(&playerObj);
FileRecorder::DestroyFileRecorder(&recObj);
return res;
}
int VoEFileImpl::ConvertPCMToCompressed(InStream* streamIn,
OutStream* streamOut,
CodecInst* compression)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ConvertPCMToCompressed(streamIn, streamOut, compression)");
if ((streamIn == NULL) || (streamOut == NULL))
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1), "invalid stream handles");
return (-1);
}
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_shared->instance_id(), -1),
" compression: plname=%s, plfreq=%d, pacsize=%d",
compression->plname, compression->plfreq,
compression->pacsize);
// Create file player object
FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
-1, kFileFormatPcm16kHzFile));
int res = playerObj.StartPlayingFile(*streamIn,0,1.0,0,0,NULL);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertPCMToCompressed failed to create player object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
return -1;
}
// Create file recorder object
FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
-1, kFileFormatCompressedFile));
res = recObj.StartRecordingAudioFile(*streamOut,*compression,0);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertPCMToCompressed failed to create recorder object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
recObj.StopRecording();
FileRecorder::DestroyFileRecorder(&recObj);
return -1;
}
// Run throught the file
AudioFrame audioFrame;
WebRtc_Word16 decodedData[160];
int decLength=0;
const WebRtc_UWord32 frequency = 16000;
while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
{
if(decLength!=frequency/100)
{
// This is an OK way to end
break;
}
res=audioFrame.UpdateFrame(-1, 0, decodedData,
(WebRtc_UWord16)decLength,
frequency, AudioFrame::kNormalSpeech,
AudioFrame::kVadActive);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertPCMToCompressed failed during conversion "
"(audio frame)");
break;
}
res=recObj.RecordAudioToFile(audioFrame);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertPCMToCompressed failed during conversion "
"(write frame)");
}
}
playerObj.StopPlayingFile();
recObj.StopRecording();
FilePlayer::DestroyFilePlayer(&playerObj);
FileRecorder::DestroyFileRecorder(&recObj);
return res;
}
int VoEFileImpl::ConvertCompressedToPCM(const char* fileNameInUTF8,
const char* fileNameOutUTF8)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ConvertCompressedToPCM(fileNameInUTF8=%s,"
" fileNameOutUTF8=%s)",
fileNameInUTF8, fileNameOutUTF8);
// Create file player object
FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
-1, kFileFormatCompressedFile));
int res = playerObj.StartPlayingFile(fileNameInUTF8,false,0,1.0,0,0,NULL);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertCompressedToPCM failed to create player object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
return -1;
}
// Create file recorder object
FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
-1, kFileFormatPcm16kHzFile));
CodecInst codecInst;
strncpy(codecInst.plname,"L16",32);
codecInst.channels = 1;
codecInst.rate = 256000;
codecInst.plfreq = 16000;
codecInst.pltype = 94;
codecInst.pacsize = 160;
res = recObj.StartRecordingAudioFile(fileNameOutUTF8,codecInst,0);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertCompressedToPCM failed to create recorder object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
recObj.StopRecording();
FileRecorder::DestroyFileRecorder(&recObj);
return -1;
}
// Run throught the file
AudioFrame audioFrame;
WebRtc_Word16 decodedData[160];
int decLength=0;
const WebRtc_UWord32 frequency = 16000;
while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
{
if(decLength!=frequency/100)
{
// This is an OK way to end
break;
}
res=audioFrame.UpdateFrame(-1, 0, decodedData,
(WebRtc_UWord16)decLength,
frequency,
AudioFrame::kNormalSpeech,
AudioFrame::kVadActive);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertCompressedToPCM failed during conversion "
"(create audio frame)");
break;
}
res=recObj.RecordAudioToFile(audioFrame);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertCompressedToPCM failed during conversion "
"(write frame)");
}
}
playerObj.StopPlayingFile();
recObj.StopRecording();
FilePlayer::DestroyFilePlayer(&playerObj);
FileRecorder::DestroyFileRecorder(&recObj);
return res;
}
int VoEFileImpl::ConvertCompressedToPCM(InStream* streamIn,
OutStream* streamOut)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"ConvertCompressedToPCM(file, file);");
if ((streamIn == NULL) || (streamOut == NULL))
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1), "invalid stream handles");
return (-1);
}
// Create file player object
FilePlayer& playerObj(*FilePlayer::CreateFilePlayer(
-1, kFileFormatCompressedFile));
int res;
res = playerObj.StartPlayingFile(*streamIn,0,1.0,0,0,NULL);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertCompressedToPCM failed to create player object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
return -1;
}
// Create file recorder object
FileRecorder& recObj(*FileRecorder::CreateFileRecorder(
-1, kFileFormatPcm16kHzFile));
CodecInst codecInst;
strncpy(codecInst.plname,"L16",32);
codecInst.channels = 1;
codecInst.rate = 256000;
codecInst.plfreq = 16000;
codecInst.pltype = 94;
codecInst.pacsize = 160;
res = recObj.StartRecordingAudioFile(*streamOut,codecInst,0);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"ConvertCompressedToPCM failed to create recorder object");
playerObj.StopPlayingFile();
FilePlayer::DestroyFilePlayer(&playerObj);
recObj.StopRecording();
FileRecorder::DestroyFileRecorder(&recObj);
return -1;
}
// Run throught the file
AudioFrame audioFrame;
WebRtc_Word16 decodedData[160];
int decLength=0;
const WebRtc_UWord32 frequency = 16000;
while(!playerObj.Get10msAudioFromFile(decodedData,decLength,frequency))
{
if(decLength!=frequency/100)
{
// This is an OK way to end
break;
}
res=audioFrame.UpdateFrame(-1, 0, decodedData,
(WebRtc_UWord16)decLength,
frequency,
AudioFrame::kNormalSpeech,
AudioFrame::kVadActive);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertCompressedToPCM failed during conversion "
"(audio frame)");
break;
}
res=recObj.RecordAudioToFile(audioFrame);
if(res)
{
WEBRTC_TRACE(kTraceError, kTraceVoice,
VoEId(_shared->instance_id(), -1),
"ConvertCompressedToPCM failed during conversion "
"(write frame)");
}
}
playerObj.StopPlayingFile();
recObj.StopRecording();
FilePlayer::DestroyFilePlayer(&playerObj);
FileRecorder::DestroyFileRecorder(&recObj);
return res;
}
int VoEFileImpl::GetFileDuration(const char* fileNameUTF8,
int& durationMs,
FileFormats format)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"GetFileDuration(fileNameUTF8=%s, format=%d)",
fileNameUTF8, format);
// Create a dummy file module for this
MediaFile * fileModule=MediaFile::CreateMediaFile(-1);
// Temp container of the right format
WebRtc_UWord32 duration;
int res=fileModule->FileDurationMs(fileNameUTF8,duration,format);
if (res)
{
_shared->SetLastError(VE_BAD_FILE, kTraceError,
"GetFileDuration() failed measure file duration");
return -1;
}
durationMs = duration;
MediaFile::DestroyMediaFile(fileModule);
fileModule = NULL;
return(res);
}
int VoEFileImpl::GetPlaybackPosition(int channel, int& positionMs)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"GetPlaybackPosition(channel=%d)", channel);
voe::ScopedChannel sc(_shared->channel_manager(), channel);
voe::Channel* channelPtr = sc.ChannelPtr();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetPlaybackPosition() failed to locate channel");
return -1;
}
return channelPtr->GetLocalPlayoutPosition(positionMs);
}
#endif // #ifdef WEBRTC_VOICE_ENGINE_FILE_API
} // namespace webrtc