Merge pull request #4989 from akallabeth/dsp_encode_resample
Added resampling to freerdp_dsp_encode.
This commit is contained in:
commit
010e3485cb
@ -770,6 +770,10 @@ set(FAAC_FEATURE_TYPE "OPTIONAL")
|
||||
set(FAAC_FEATURE_PURPOSE "codec")
|
||||
set(FAAC_FEATURE_DESCRIPTION "FAAC AAC audio codec library")
|
||||
|
||||
set(SOXR_FEATURE_TYPE "OPTIONAL")
|
||||
set(SOXR_FEATURE_PURPOSE "codec")
|
||||
set(SOXR_FEATURE_DESCRIPTION "SOX audio resample library")
|
||||
|
||||
set(GSSAPI_FEATURE_TYPE "OPTIONAL")
|
||||
set(GSSAPI_FEATURE_PURPOSE "auth")
|
||||
set(GSSAPI_FEATURE_DESCRIPTION "add kerberos support")
|
||||
@ -873,6 +877,7 @@ find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRI
|
||||
find_feature(LAME ${LAME_FEATURE_TYPE} ${LAME_FEATURE_PURPOSE} ${LAME_FEATURE_DESCRIPTION})
|
||||
find_feature(FAAD2 ${FAAD2_FEATURE_TYPE} ${FAAD2_FEATURE_PURPOSE} ${FAAD2_FEATURE_DESCRIPTION})
|
||||
find_feature(FAAC ${FAAC_FEATURE_TYPE} ${FAAC_FEATURE_PURPOSE} ${FAAC_FEATURE_DESCRIPTION})
|
||||
find_feature(soxr ${SOXR_FEATURE_TYPE} ${SOXR_FEATURE_PURPOSE} ${SOXR_FEATURE_DESCRIPTION})
|
||||
|
||||
find_feature(GSSAPI ${GSSAPI_FEATURE_TYPE} ${GSSAPI_FEATURE_PURPOSE} ${GSSAPI_FEATURE_DESCRIPTION})
|
||||
|
||||
|
@ -341,6 +341,7 @@ static UINT audin_receive_wave_data(const AUDIO_FORMAT* format,
|
||||
const BYTE* data, size_t size, void* user_data)
|
||||
{
|
||||
UINT error;
|
||||
BOOL compatible;
|
||||
AUDIN_PLUGIN* audin;
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) user_data;
|
||||
|
||||
@ -362,7 +363,8 @@ static UINT audin_receive_wave_data(const AUDIO_FORMAT* format,
|
||||
|
||||
Stream_Write_UINT8(audin->data, MSG_SNDIN_DATA);
|
||||
|
||||
if (audin->device->FormatSupported(audin->device, audin->format))
|
||||
compatible = audio_format_compatible(format, audin->format);
|
||||
if (compatible && audin->device->FormatSupported(audin->device, audin->format))
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(audin->data, size))
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
@ -408,8 +410,31 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb
|
||||
|
||||
if (!supported)
|
||||
{
|
||||
/* Default sample rates supported by most backends. */
|
||||
const UINT32 samplerates[] = {
|
||||
96000,
|
||||
48000,
|
||||
44100,
|
||||
22050
|
||||
};
|
||||
BOOL test = FALSE;
|
||||
|
||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
format.wBitsPerSample = 16;
|
||||
test = IFCALLRESULT(FALSE, audin->device->FormatSupported, audin->device, &format);
|
||||
if (!test)
|
||||
{
|
||||
size_t x;
|
||||
for (x=0; x<ARRAYSIZE(samplerates); x++)
|
||||
{
|
||||
format.nSamplesPerSec = samplerates[x];
|
||||
test = IFCALLRESULT(FALSE, audin->device->FormatSupported, audin->device, &format);
|
||||
if (test)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!test)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
IFCALLRET(audin->device->SetFormat, error,
|
||||
|
@ -306,7 +306,7 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length
|
||||
AudinPulseDevice* pulse = (AudinPulseDevice*) userdata;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
pa_stream_peek(stream, &data, &length);
|
||||
error = pulse->receive(&pulse->format, data, length, pulse->user_data);
|
||||
error = IFCALLRESULT(CHANNEL_RC_OK, pulse->receive, &pulse->format, data, length, pulse->user_data);
|
||||
pa_stream_drop(stream);
|
||||
|
||||
if (error && pulse->rdpcontext)
|
||||
|
@ -301,8 +301,7 @@ static UINT rdpsnd_server_select_format(RdpsndServerContext* context,
|
||||
AUDIO_FORMAT* format;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if ((client_format_index < 0)
|
||||
|| (client_format_index >= context->num_client_formats)
|
||||
if ((client_format_index >= context->num_client_formats)
|
||||
|| (!context->src_format))
|
||||
{
|
||||
WLog_ERR(TAG, "index %d is not correct.", client_format_index);
|
||||
@ -415,6 +414,10 @@ static UINT rdpsnd_server_send_wave_pdu(RdpsndServerContext* context,
|
||||
ULONG written;
|
||||
wStream* s = context->priv->rdpsnd_pdu;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (context->selected_client_format >= context->num_client_formats)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
format = &context->client_formats[context->selected_client_format];
|
||||
/* WaveInfo PDU */
|
||||
Stream_SetPosition(s, 0);
|
||||
@ -429,7 +432,7 @@ static UINT rdpsnd_server_send_wave_pdu(RdpsndServerContext* context,
|
||||
src = context->priv->out_buffer;
|
||||
length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
|
||||
|
||||
if (!freerdp_dsp_encode(context->priv->dsp_context, format, src, length, s))
|
||||
if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
else
|
||||
{
|
||||
@ -491,6 +494,10 @@ static UINT rdpsnd_server_send_wave2_pdu(RdpsndServerContext* context,
|
||||
ULONG written;
|
||||
wStream* s = context->priv->rdpsnd_pdu;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (context->selected_client_format >= context->num_client_formats)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
format = &context->client_formats[context->selected_client_format];
|
||||
/* WaveInfo PDU */
|
||||
Stream_SetPosition(s, 0);
|
||||
@ -501,11 +508,11 @@ static UINT rdpsnd_server_send_wave2_pdu(RdpsndServerContext* context,
|
||||
Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */
|
||||
Stream_Write_UINT8(s, context->block_no); /* cBlockNo */
|
||||
Stream_Seek(s, 3); /* bPad */
|
||||
Stream_Write_UINT16(s, wTimestamp); /* dwAudioTimeStamp */
|
||||
Stream_Write_UINT32(s, wTimestamp); /* dwAudioTimeStamp */
|
||||
src = context->priv->out_buffer;
|
||||
length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame;
|
||||
|
||||
if (!freerdp_dsp_encode(context->priv->dsp_context, format, src, length, s))
|
||||
if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s))
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
else
|
||||
{
|
||||
@ -558,7 +565,7 @@ static UINT rdpsnd_server_send_samples(RdpsndServerContext* context,
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
EnterCriticalSection(&context->priv->lock);
|
||||
|
||||
if (context->selected_client_format < 0)
|
||||
if (context->selected_client_format >= context->num_client_formats)
|
||||
{
|
||||
/* It's possible while format negotiation has not been done */
|
||||
WLog_WARN(TAG, "Drop samples because client format has not been negotiated.");
|
||||
@ -636,7 +643,7 @@ static UINT rdpsnd_server_close(RdpsndServerContext* context)
|
||||
|
||||
if (context->priv->out_pending_frames > 0)
|
||||
{
|
||||
if (context->selected_client_format < 0)
|
||||
if (context->selected_client_format >= context->num_client_formats)
|
||||
{
|
||||
WLog_ERR(TAG, "Pending audio frame exists while no format selected.");
|
||||
error = ERROR_INVALID_DATA;
|
||||
@ -652,7 +659,7 @@ static UINT rdpsnd_server_close(RdpsndServerContext* context)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
context->selected_client_format = -1;
|
||||
context->selected_client_format = 0xFFFF;
|
||||
Stream_Write_UINT8(s, SNDC_CLOSE);
|
||||
Stream_Write_UINT8(s, 0);
|
||||
Stream_Seek_UINT16(s);
|
||||
@ -807,7 +814,7 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
|
||||
context->vcm = vcm;
|
||||
context->Start = rdpsnd_server_start;
|
||||
context->Stop = rdpsnd_server_stop;
|
||||
context->selected_client_format = -1;
|
||||
context->selected_client_format = 0xFFFF;
|
||||
context->Initialize = rdpsnd_server_initialize;
|
||||
context->SelectFormat = rdpsnd_server_select_format;
|
||||
context->SendSamples = rdpsnd_server_send_samples;
|
||||
|
62
cmake/Findsoxr.cmake
Normal file
62
cmake/Findsoxr.cmake
Normal file
@ -0,0 +1,62 @@
|
||||
# Try to find the soxr library
|
||||
#
|
||||
# Copyright 2018 Thincast Technologies GmbH
|
||||
# Copyright 2018 Armin Novak <armin.novak@thincast.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# SOXR_ROOT - A list of search hints
|
||||
#
|
||||
# SOXR_FOUND - system has soxr
|
||||
# SOXR_INCLUDE_DIR - the soxr include directory
|
||||
# SOXR_LIBRARIES - libsoxr library
|
||||
|
||||
if (UNIX AND NOT ANDROID)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_SOXR QUIET soxr)
|
||||
endif (UNIX AND NOT ANDROID)
|
||||
|
||||
if (SOXR_INCLUDE_DIR AND SOXR_LIBRARY)
|
||||
set(SOXR_FIND_QUIETLY TRUE)
|
||||
endif (SOXR_INCLUDE_DIR AND SOXR_LIBRARY)
|
||||
|
||||
find_path(SOXR_INCLUDE_DIR NAMES soxr.h
|
||||
PATH_SUFFIXES include
|
||||
HINTS ${SOXR_ROOT} ${PC_SOXR_INCLUDE_DIRS})
|
||||
find_library(SOXR_LIBRARY
|
||||
NAMES soxr
|
||||
PATH_SUFFIXES lib
|
||||
HINTS ${SOXR_ROOT} ${PC_SOXR_LIBRARY_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(soxr DEFAULT_MSG SOXR_LIBRARY SOXR_INCLUDE_DIR)
|
||||
|
||||
if (SOXR_INCLUDE_DIR AND SOXR_LIBRARY)
|
||||
set(SOXR_FOUND TRUE)
|
||||
set(SOXR_INCLUDE_DIRS ${SOXR_INCLUDE_DIR})
|
||||
set(SOXR_LIBRARIES ${SOXR_LIBRARY})
|
||||
endif (SOXR_INCLUDE_DIR AND SOXR_LIBRARY)
|
||||
|
||||
if (SOXR_FOUND)
|
||||
if (NOT SOXR_FIND_QUIETLY)
|
||||
message(STATUS "Found soxr: ${SOXR_LIBRARIES}")
|
||||
endif (NOT SOXR_FIND_QUIETLY)
|
||||
else (SOXR_FOUND)
|
||||
if (SOXR_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "soxr was not found")
|
||||
endif(SOXR_FIND_REQUIRED)
|
||||
endif (SOXR_FOUND)
|
||||
|
||||
mark_as_advanced(SOXR_INCLUDE_DIR SOXR_LIBRARY)
|
||||
|
@ -57,6 +57,7 @@
|
||||
#cmakedefine WITH_LAME
|
||||
#cmakedefine WITH_FAAD2
|
||||
#cmakedefine WITH_FAAC
|
||||
#cmakedefine WITH_SOXR
|
||||
#cmakedefine WITH_GFX_H264
|
||||
#cmakedefine WITH_OPENH264
|
||||
#cmakedefine WITH_FFMPEG
|
||||
|
@ -162,6 +162,11 @@ if (WITH_DSP_FFMPEG)
|
||||
codec/dsp_ffmpeg.h)
|
||||
endif (WITH_DSP_FFMPEG)
|
||||
|
||||
if (WITH_SOXR)
|
||||
freerdp_library_add(${SOXR_LIBRARIES})
|
||||
include_directories(${SOXR_INCLUDE_DIR})
|
||||
endif(WITH_SOXR)
|
||||
|
||||
if(GSM_FOUND)
|
||||
freerdp_library_add(${GSM_LIBRARIES})
|
||||
include_directories(${GSM_INCLUDE_DIRS})
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -28,8 +29,10 @@
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
|
||||
#if !defined(WITH_DSP_FFMPEG)
|
||||
#if defined(WITH_GSM)
|
||||
#include <gsm/gsm.h>
|
||||
#endif
|
||||
@ -38,10 +41,6 @@
|
||||
#include <lame/lame.h>
|
||||
#endif
|
||||
|
||||
#if defined(WITH_DSP_FFMPEG)
|
||||
#include "dsp_ffmpeg.h"
|
||||
#endif
|
||||
|
||||
#if defined(WITH_FAAD2)
|
||||
#include <neaacdec.h>
|
||||
#endif
|
||||
@ -50,8 +49,18 @@
|
||||
#include <faac.h>
|
||||
#endif
|
||||
|
||||
#if defined(WITH_SOXR)
|
||||
#include <soxr.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include "dsp_ffmpeg.h"
|
||||
#endif
|
||||
|
||||
#define TAG FREERDP_TAG("dsp")
|
||||
|
||||
#if !defined(WITH_DSP_FFMPEG)
|
||||
|
||||
union _ADPCM
|
||||
{
|
||||
struct
|
||||
@ -96,6 +105,10 @@ struct _FREERDP_DSP_CONTEXT
|
||||
unsigned long faacInputSamples;
|
||||
unsigned long faacMaxOutputBytes;
|
||||
#endif
|
||||
|
||||
#if defined(WITH_SOXR)
|
||||
soxr_t sox;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@ -104,47 +117,64 @@ struct _FREERDP_DSP_CONTEXT
|
||||
*/
|
||||
|
||||
static BOOL freerdp_dsp_resample(FREERDP_DSP_CONTEXT* context,
|
||||
const BYTE* src, size_t bytes_per_sample,
|
||||
UINT32 schan, UINT32 srate, size_t sframes,
|
||||
UINT32 rchan, UINT32 rrate)
|
||||
const BYTE* src, size_t size,
|
||||
const AUDIO_FORMAT* srcFormat,
|
||||
const BYTE** data, size_t* length)
|
||||
{
|
||||
BYTE* p;
|
||||
int rframes;
|
||||
int rsize;
|
||||
int i, j;
|
||||
int n1, n2;
|
||||
int sbytes, rbytes;
|
||||
sbytes = bytes_per_sample * schan;
|
||||
rbytes = bytes_per_sample * rchan;
|
||||
rframes = sframes * rrate / srate;
|
||||
rsize = rbytes * rframes;
|
||||
#if defined(WITH_SOXR)
|
||||
soxr_error_t error;
|
||||
size_t idone, odone;
|
||||
#endif
|
||||
size_t sframes, rframes;
|
||||
size_t rsize;
|
||||
size_t j;
|
||||
size_t sbytes, rbytes;
|
||||
size_t srcBytesPerFrame, dstBytesPerFrame;
|
||||
size_t srcChannels, dstChannels;
|
||||
AUDIO_FORMAT format;
|
||||
|
||||
if (!Stream_EnsureCapacity(context->resample, rsize + 1024))
|
||||
return FALSE;
|
||||
|
||||
p = Stream_Buffer(context->resample);
|
||||
|
||||
for (i = 0; i < rframes; i++)
|
||||
if (srcFormat->wFormatTag != WAVE_FORMAT_PCM)
|
||||
{
|
||||
n1 = i * srate / rrate;
|
||||
|
||||
if (n1 >= sframes)
|
||||
n1 = sframes - 1;
|
||||
|
||||
n2 = (n1 * rrate == i * srate || n1 == sframes - 1 ? n1 : n1 + 1);
|
||||
|
||||
for (j = 0; j < rbytes; j++)
|
||||
{
|
||||
/* Nearest Interpolation, probably the easiest, but works */
|
||||
*p++ = (i * srate - n1 * rrate > n2 * rrate - i * srate ?
|
||||
src[n2 * sbytes + (j % sbytes)] :
|
||||
src[n1 * sbytes + (j % sbytes)]);
|
||||
}
|
||||
WLog_ERR(TAG, "%s requires %s for sample input, got %s", __FUNCTION__,
|
||||
audio_format_get_tag_string(WAVE_FORMAT_PCM),
|
||||
audio_format_get_tag_string(srcFormat->wFormatTag));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_SetPointer(context->resample, p);
|
||||
Stream_SealLength(context->resample);
|
||||
return TRUE;
|
||||
srcChannels = srcFormat->nChannels;
|
||||
dstChannels = context->format.nChannels;
|
||||
srcBytesPerFrame = (srcFormat->wBitsPerSample > 8) ? 2 : 1;
|
||||
dstBytesPerFrame = (context->format.wBitsPerSample > 8) ? 2 : 1;
|
||||
/* We want to ignore differences of source and destination format. */
|
||||
format = *srcFormat;
|
||||
format.wFormatTag = WAVE_FORMAT_UNKNOWN;
|
||||
|
||||
if (audio_format_compatible(&format, &context->format))
|
||||
return TRUE;
|
||||
|
||||
#if defined(WITH_SOXR)
|
||||
sbytes = srcChannels * srcBytesPerFrame;
|
||||
sframes = size / sbytes;
|
||||
rbytes = dstBytesPerFrame * dstChannels;
|
||||
/* Integer rounding correct division */
|
||||
rframes = (sframes * context->format.nSamplesPerSec + (srcFormat->nSamplesPerSec + 1) / 2) /
|
||||
srcFormat->nSamplesPerSec;
|
||||
rsize = rframes * rbytes;
|
||||
|
||||
if (!Stream_EnsureCapacity(context->resample, rsize))
|
||||
return FALSE;
|
||||
|
||||
error = soxr_process(context->sox, src, sframes, &idone,
|
||||
Stream_Buffer(context->resample),
|
||||
Stream_Capacity(context->resample) / rbytes, &odone);
|
||||
Stream_SetLength(context->resample, odone * rbytes);
|
||||
*data = Stream_Buffer(context->resample);
|
||||
*length = Stream_Length(context->resample);
|
||||
return (error == 0) ? TRUE : FALSE;
|
||||
#else
|
||||
WLog_ERR(TAG, "Missing resample support, recompile -DWITH_SOXR=ON or -DWITH_DSP_FFMPEG=ON");
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -411,16 +441,18 @@ static BOOL freerdp_dsp_encode_faac(FREERDP_DSP_CONTEXT* context,
|
||||
{
|
||||
int16_t* inSamples = (int16_t*)src;
|
||||
int32_t* outSamples;
|
||||
unsigned int bpp;
|
||||
unsigned int nrSamples, x;
|
||||
int rc;
|
||||
|
||||
if (!context || !src || !out)
|
||||
return FALSE;
|
||||
|
||||
nrSamples = size / context->format.nChannels / context->format.wBitsPerSample / 8;
|
||||
bpp = context->format.wBitsPerSample / 8 * context->format.nChannels;
|
||||
nrSamples = size / bpp;
|
||||
|
||||
if (!Stream_EnsureCapacity(context->buffer,
|
||||
context->faacInputSamples * sizeof(int32_t) * context->format.nChannels))
|
||||
nrSamples * sizeof(int32_t) * context->format.nChannels))
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(out, context->faacMaxOutputBytes))
|
||||
@ -911,6 +943,8 @@ static BOOL freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* context, const BYTE
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FREERDP_DSP_CONTEXT* freerdp_dsp_context_new(BOOL encoder)
|
||||
{
|
||||
#if defined(WITH_DSP_FFMPEG)
|
||||
@ -1015,6 +1049,9 @@ void freerdp_dsp_context_free(FREERDP_DSP_CONTEXT* context)
|
||||
if (context->faac)
|
||||
faacEncClose(context->faac);
|
||||
|
||||
#endif
|
||||
#if defined(WITH_SOXR)
|
||||
soxr_delete(context->sox);
|
||||
#endif
|
||||
free(context);
|
||||
}
|
||||
@ -1032,7 +1069,8 @@ BOOL freerdp_dsp_encode(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT* srcFor
|
||||
if (!context || !context->encoder || !srcFormat || !data || !out)
|
||||
return FALSE;
|
||||
|
||||
// TODO: Resample
|
||||
if (!freerdp_dsp_resample(context, data, length, srcFormat, &data, &length))
|
||||
return FALSE;
|
||||
|
||||
switch (context->format.wFormatTag)
|
||||
{
|
||||
@ -1129,9 +1167,13 @@ BOOL freerdp_dsp_supports_format(const AUDIO_FORMAT* format, BOOL encode)
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
return TRUE;
|
||||
#if defined(WITH_DSP_EXPERIMENTAL)
|
||||
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
return TRUE;
|
||||
#endif
|
||||
#if defined(WITH_GSM)
|
||||
|
||||
case WAVE_FORMAT_GSM610:
|
||||
@ -1172,7 +1214,6 @@ BOOL freerdp_dsp_supports_format(const AUDIO_FORMAT* format, BOOL encode)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT* targetFormat)
|
||||
{
|
||||
#if defined(WITH_DSP_FFMPEG)
|
||||
@ -1206,6 +1247,18 @@ BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT*
|
||||
faacEncSetConfiguration(context->faac, cfg);
|
||||
}
|
||||
|
||||
#endif
|
||||
#if defined(WITH_SOXR)
|
||||
{
|
||||
soxr_io_spec_t iospec = soxr_io_spec(SOXR_INT16, SOXR_INT16);
|
||||
soxr_error_t error;
|
||||
soxr_delete(context->sox);
|
||||
context->sox = soxr_create(context->format.nSamplesPerSec, targetFormat->nSamplesPerSec,
|
||||
targetFormat->nChannels, &error, &iospec, NULL, NULL);
|
||||
|
||||
if (!context->sox || (error != 0))
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user