From 1d2ea0875c1b5409704ff6a17605afbed674125d Mon Sep 17 00:00:00 2001 From: Andrea Bondavalli Date: Fri, 10 Apr 2020 13:04:44 -0700 Subject: [PATCH] Added support for AM824 codec for testing - added patch to ravenna-alsa-lkm module to support AM824 codec and associated conversion functions - added support for AM824 codec to daemon and in WebUI - modifed demo to test 8 channels of AM824 with 6 samples per packet @ 48Khz (125us x packet) --- .../ravenna-alsa-lkm-added-codec-am824.patch | 163 ++++++++++++++++++ build.sh | 1 + daemon/session_manager.cpp | 2 +- demo/daemon.conf | 2 +- demo/status.json | 10 +- run_demo.sh | 4 +- webui/src/SourceEdit.js | 1 + 7 files changed, 174 insertions(+), 9 deletions(-) create mode 100644 3rdparty/patches/ravenna-alsa-lkm-added-codec-am824.patch diff --git a/3rdparty/patches/ravenna-alsa-lkm-added-codec-am824.patch b/3rdparty/patches/ravenna-alsa-lkm-added-codec-am824.patch new file mode 100644 index 0000000..7278a5b --- /dev/null +++ b/3rdparty/patches/ravenna-alsa-lkm-added-codec-am824.patch @@ -0,0 +1,163 @@ +diff --git a/driver/MTConvert.c b/driver/MTConvert.c +index c94bc03..75063a1 100644 +--- a/driver/MTConvert.c ++++ b/driver/MTConvert.c +@@ -2097,6 +2097,95 @@ void MTConvertBigEndianInt24ToMappedInt32DeInterleave( void* input_buffer, + }*/ + + ++void MTConvertMappedInt32ToBigEndianInt32Interleave(void** input_buffer, ++ const uint32_t offset_input_buf, ++ void* output_buffer, ++ const uint32_t nb_channels, ++ const uint32_t nb_samples_in) ++{ ++ ++ uint32_t i, ch; ++ uint8_t* out = (uint8_t*)output_buffer; ++ const unsigned int stride_in = 4; ++ unsigned int in_pos = offset_input_buf * stride_in; ++ for(i = offset_input_buf; i < offset_input_buf + nb_samples_in; ++i) ++ { ++ if(Arch_is_big_endian()) ++ { ++ for(ch = 0; ch < nb_channels; ++ch) ++ { ++ const uint8_t* in = (uint8_t*)input_buffer[ch] + in_pos; ++ out[0] = in[0]; ++ out[1] = in[1]; ++ out[2] = in[2]; ++ out[3] = in[3]; ++ out += 4; ++ } ++ } ++ else ++ { ++ for(ch = 0; ch < nb_channels; ++ch) ++ { ++ const uint8_t* in = (uint8_t*)input_buffer[ch] + in_pos; ++ out[0] = in[3]; ++ out[1] = in[2]; ++ out[2] = in[1]; ++ out[3] = in[0]; ++ out += 4; ++ } ++ } ++ in_pos += stride_in; ++ } ++} ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++// Convert from an interleave buffer to N non-interleave buffers ++// i.e. [A0.B0.A1.B1...A(dwNbOfSamplesByChannels-1).B(dwNbOfSamplesByChannels-1)] -> [A0..A(dwNbOfSamplesByChannels-1)][B0..B(dwNbOfSamplesByChannels-1)] ++void MTConvertBigEndianInt32ToMappedInt32DeInterleave( void* input_buffer, ++ void** output_buffer, ++ uint32_t offset_output_buf, ++ uint32_t nb_channels, ++ uint32_t nb_samples) ++{ ++ uint32_t i, ch; ++ const unsigned int stride_in = 4 * nb_channels, stride_out = 4; ++ const unsigned int out_pos = offset_output_buf * stride_out; ++ for(ch = 0; ch < nb_channels; ++ch) ++ { ++ uint8_t* in = (uint8_t*)input_buffer + 4 * ch; ++ uint8_t* out = (uint8_t*)output_buffer[ch] + out_pos; ++ ++ if(Arch_is_big_endian()) ++ { ++ for(i = 0; i < nb_samples; ++i) ++ { ++ out[0] = in[0]; ++ out[1] = in[1]; ++ out[2] = in[2]; ++ out[3] = in[3]; ++ ++ in += stride_in; ++ out += stride_out; ++ } ++ } ++ else ++ { ++ for(i = 0; i < nb_samples; ++i) ++ { ++ out[0] = in[3]; ++ out[1] = in[2]; ++ out[2] = in[1]; ++ out[3] = in[0]; ++ ++ in += stride_in; ++ out += stride_out; ++ } ++ } ++ } ++} ++ + + /////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// +diff --git a/driver/MTConvert.h b/driver/MTConvert.h +index 54bc90e..483f1c6 100644 +--- a/driver/MTConvert.h ++++ b/driver/MTConvert.h +@@ -121,6 +121,8 @@ void MTConvertMappedInt24ToBigEndianInt24Interleave(void** ppi24Uninterleave, co + void MTConvertBigEndianInt24ToMappedInt24DeInterleave(void* pbyBigEndianInterleave, void** ppi24Uninterleave, uint32_t dwOffsetInUninterleaveBuffer, uint32_t dwNbOfChannels, uint32_t dwNbOfSamplesByChannels); + void MTConvertMappedInt32ToBigEndianInt24Interleave(void** ppi32Uninterleave, const uint32_t dwOffsetInUninterleaveBuffer, void* pbyBigEndianInterleave, const uint32_t dwNbOfChannels, const uint32_t dwNbOfSamplesByChannels); + void MTConvertBigEndianInt24ToMappedInt32DeInterleave(void* pbyBigEndianInterleave, void** ppi32Uninterleave, uint32_t dwOffsetInUninterleaveBuffer, uint32_t dwNbOfChannels, uint32_t dwNbOfSamplesByChannels); ++void MTConvertMappedInt32ToBigEndianInt32Interleave(void** ppi32Uninterleave, const uint32_t dwOffsetInUninterleaveBuffer, void* pbyBigEndianInterleave, const uint32_t dwNbOfChannels, const uint32_t dwNbOfSamplesByChannels); ++void MTConvertBigEndianInt32ToMappedInt32DeInterleave(void* pbyBigEndianInterleave, void** ppi32Uninterleave, uint32_t dwOffsetInUninterleaveBuffer, uint32_t dwNbOfChannels, uint32_t dwNbOfSamplesByChannels); + + // DSD + void MTConvertMappedFloatToBigEndianDSD64Interleave(void** ppfUninterleave, const uint32_t dwOffsetInUninterleaveBuffer, void* pvBigEndianInterleave, const uint32_t dwNbOfChannels, const uint32_t dwNbOfSamplesByChannels); +diff --git a/driver/RTP_audio_stream.c b/driver/RTP_audio_stream.c +index 5a160e4..403a51a 100644 +--- a/driver/RTP_audio_stream.c ++++ b/driver/RTP_audio_stream.c +@@ -170,6 +171,10 @@ int Create(TRTP_audio_stream* self, TRTP_stream_info* pRTP_stream_info, rtp_audi + { + self->m_pfnMTConvertMappedToInterleave = &MTConvertMappedInt32ToBigEndianInt24Interleave; + } ++ else if(strcmp(pRTP_stream_info->m_cCodec, "AM824") == 0) ++ { ++ self->m_pfnMTConvertMappedToInterleave = &MTConvertMappedInt32ToBigEndianInt32Interleave; ++ } + else if(strcmp(pRTP_stream_info->m_cCodec, "DSD64_32") == 0 || strcmp(pRTP_stream_info->m_cCodec, "DSD128_32") == 0 || strcmp(pRTP_stream_info->m_cCodec, "DSD256") == 0) + { + self->m_pfnMTConvertMappedToInterleave = &MTConvertMappedFloatToBigEndianDSD256Interleave; +@@ -300,6 +305,10 @@ int Create(TRTP_audio_stream* self, TRTP_stream_info* pRTP_stream_info, rtp_audi + { + self->m_pfnMTConvertInterleaveToMapped = &MTConvertBigEndianInt24ToMappedInt32DeInterleave; + } ++ else if(strcmp(pRTP_stream_info->m_cCodec, "AM824") == 0) ++ { ++ self->m_pfnMTConvertInterleaveToMapped = &MTConvertBigEndianInt32ToMappedInt32DeInterleave; ++ } + else + { + MTAL_DP("CRTP_audio_stream::Init: invalid Codec\n"); +diff --git a/driver/RTP_stream_info.c b/driver/RTP_stream_info.c +index ac65bbb..83ee967 100644 +--- a/driver/RTP_stream_info.c ++++ b/driver/RTP_stream_info.c +@@ -168,7 +168,7 @@ int is_valid(TRTP_stream_info* rtp_stream_info) + { + char* cCodec = rtp_stream_info->m_cCodec; + if (strcmp(cCodec, "L16") && strcmp(cCodec, "L24") && strcmp(cCodec, "L2432") +- && strcmp(cCodec, "DSD64_32") && strcmp(cCodec, "DSD128_32") ++ && strcmp(cCodec, "AM824") && strcmp(cCodec, "DSD64_32") && strcmp(cCodec, "DSD128_32") + && strcmp(cCodec, "DSD64") && strcmp(cCodec, "DSD128") && strcmp(cCodec, "DSD256")) + { + MTAL_DP("CRTP_stream_info::IsValid: wrong codec = %s\n", cCodec); +@@ -252,6 +252,10 @@ unsigned char get_codec_word_lenght(const char* cCodec) + { + return 4; + } ++ else if (strcmp(cCodec, "AM824") == 0) ++ { ++ return 4; ++ } + else if (strcmp(cCodec, "DSD64") == 0) + { + return 1; diff --git a/build.sh b/build.sh index eb45a45..12a5f29 100755 --- a/build.sh +++ b/build.sh @@ -18,6 +18,7 @@ if [ ! -d ravenna-alsa-lkm.git ]; then git apply ../../patches/ravenna-alsa-lkm-enable-loopback.patch git apply ../../patches/ravenna-alsa-lkm-fixes.patch git apply ../../patches/ravenna-alsa-lkm-arm-32bit.patch + git apply ../../patches/ravenna-alsa-lkm-added-codec-am824.patch echo "Building ravenna-alsa-lkm kernel module ..." make cd ../.. diff --git a/daemon/session_manager.cpp b/daemon/session_manager.cpp index b452814..e122cec 100644 --- a/daemon/session_manager.cpp +++ b/daemon/session_manager.cpp @@ -45,7 +45,7 @@ static uint8_t get_codec_word_lenght(const std::string& codec) { if (codec == "L24") { return 3; } - if (codec == "L2432") { + if (codec == "L2432" || codec == "AM824") { return 4; } if (codec == "DSD64") { diff --git a/demo/daemon.conf b/demo/daemon.conf index 0c10fe5..5a6c3c4 100644 --- a/demo/daemon.conf +++ b/demo/daemon.conf @@ -5,7 +5,7 @@ "playout_delay": 0, "tic_frame_size_at_1fs": 192, "max_tic_frame_size": 1024, - "sample_rate": 44100, + "sample_rate": 48000, "rtp_mcast_base": "239.1.0.1", "rtp_port": 5004, "ptp_domain": 0, diff --git a/demo/status.json b/demo/status.json index f329272..58d0082 100644 --- a/demo/status.json +++ b/demo/status.json @@ -5,13 +5,13 @@ "enabled": true, "name": "ALSA Source 0", "io": "Audio Device", - "max_samples_per_packet": 48, - "codec": "L16", + "max_samples_per_packet": 6, + "codec": "AM824", "ttl": 15, "payload_type": 98, "dscp": 34, "refclk_ptp_traceable": false, - "map": [ 0, 1 ] + "map": [ 0, 1, 2, 3, 4, 5, 6, 7 ] } ], "sinks": [ { @@ -20,9 +20,9 @@ "io": "Audio Device", "use_sdp": true, "source": "http://127.0.0.1:8080/api/source/sdp/0", - "sdp": "v=0\no=- 0 0 IN IP4 127.0.0.1\ns=ALSA Source 0\nc=IN IP4 239.1.0.1/15\nt=0 0\na=clock-domain:PTPv2 0\nm=audio 5004 RTP/AVP 98\nc=IN IP4 239.1.0.1/15\na=rtpmap:98 L16/44100/2\na=sync-time:0\na=framecount:48\na=ptime:1.08843537415\na=mediaclk:direct=0\na=ts-refclk:ptp=IEEE1588-2008:00-00-00-FF-FE-00-00-00:0\na=recvonly\n", + "sdp": "v=0\no=- 0 0 IN IP4 127.0.0.1\ns=ALSA Source 0\nc=IN IP4 239.1.0.1/15\nt=0 0\na=clock-domain:PTPv2 0\nm=audio 5004 RTP/AVP 98\nc=IN IP4 239.1.0.1/15\na=rtpmap:98 AM824/48000/8\na=sync-time:0\na=framecount:48\na=ptime:0.125\na=mediaclk:direct=0\na=ts-refclk:ptp=IEEE1588-2008:00-00-00-FF-FE-00-00-00:0\na=recvonly\n", "delay": 576, "ignore_refclk_gmid": true, - "map": [ 0, 1 ] + "map": [ 0, 1, 2, 3, 4, 5, 6, 7 ] } ] } diff --git a/run_demo.sh b/run_demo.sh index aca11e9..56e09a5 100755 --- a/run_demo.sh +++ b/run_demo.sh @@ -76,12 +76,12 @@ sleep 30 #starting recording on sink echo "Starting to record 60 secs from sink ..." -arecord -D plughw:RAVENNA -f cd -d 60 -r 44100 -c 2 -t wav /tmp/sink_test.wav > /dev/null 2>&1 & +arecord -D plughw:RAVENNA -f S32_LE -d 60 -r 48000 -c 8 -t wav /tmp/sink_test.wav > /dev/null 2>&1 & sleep 10 #starting playback on source echo "Starting to playback test on source ..." -speaker-test -D plughw:RAVENNA -r 44100 -c 2 -t sine > /dev/null 2>&1 & +speaker-test -F S32_LE -D plughw:RAVENNA -r 48000 -c 8 -t sine > /dev/null 2>&1 & while killall -0 arecord 2>/dev/null ; do sleep 1 diff --git a/webui/src/SourceEdit.js b/webui/src/SourceEdit.js index aeb0a85..24f99d8 100644 --- a/webui/src/SourceEdit.js +++ b/webui/src/SourceEdit.js @@ -201,6 +201,7 @@ class SourceEdit extends Component {