diff --git a/include/system/nxplayer.h b/include/system/nxplayer.h index aea4d2d42..700d0e931 100644 --- a/include/system/nxplayer.h +++ b/include/system/nxplayer.h @@ -506,6 +506,23 @@ int nxplayer_systemreset(FAR struct nxplayer_s *pplayer); int nxplayer_parse_mp3(int fd, FAR uint32_t *samplerate, FAR uint8_t *chans, FAR uint8_t *bps); +/**************************************************************************** + * Name: nxplayer_parse_sbc + * + * Performs pre-process when play sbc file. + * Parse samplerate, channels, bps. + * + * Input Parameters: + * pplayer - Pointer to the context to initialize + * + * Returned Value: + * OK if file parsed successfully. + * + ****************************************************************************/ + +int nxplayer_parse_sbc(int fd, FAR uint32_t *samplerate, + FAR uint8_t *chans, FAR uint8_t *bps); + /**************************************************************************** * Name: nxplayer_fill_mp3 * diff --git a/system/nxplayer/CMakeLists.txt b/system/nxplayer/CMakeLists.txt index 7faf55d2e..82ef6d131 100644 --- a/system/nxplayer/CMakeLists.txt +++ b/system/nxplayer/CMakeLists.txt @@ -27,7 +27,7 @@ if(CONFIG_SYSTEM_NXPLAYER) endif() target_sources(apps PRIVATE nxplayer.c) - set(CSRCS nxplayer.c nxplayer_common.c nxplayer_mp3.c) + set(CSRCS nxplayer.c nxplayer_common.c nxplayer_mp3.c nxplayer_sbc.c) target_sources(apps PRIVATE ${CSRCS}) endif() diff --git a/system/nxplayer/Makefile b/system/nxplayer/Makefile index 8741d0f79..02e77446f 100644 --- a/system/nxplayer/Makefile +++ b/system/nxplayer/Makefile @@ -25,6 +25,7 @@ include $(APPDIR)/Make.defs CSRCS = nxplayer.c CSRCS += nxplayer_common.c CSRCS += nxplayer_mp3.c +CSRCS += nxplayer_sbc.c ifneq ($(CONFIG_NXPLAYER_COMMAND_LINE),) PROGNAME = nxplayer diff --git a/system/nxplayer/nxplayer.c b/system/nxplayer/nxplayer.c index 77a1d5913..626000982 100644 --- a/system/nxplayer/nxplayer.c +++ b/system/nxplayer/nxplayer.c @@ -92,6 +92,9 @@ int nxplayer_getmidisubformat(int fd); int nxplayer_getmp3subformat(int fd); #endif +#ifdef CONFIG_AUDIO_FORMAT_SBC +int nxplayer_getsbcsubformat(int fd); +#endif /**************************************************************************** * Private Data ****************************************************************************/ @@ -119,7 +122,10 @@ static const struct nxplayer_ext_fmt_s g_known_ext[] = { "midi", AUDIO_FMT_MIDI, nxplayer_getmidisubformat }, #endif #ifdef CONFIG_AUDIO_FORMAT_OGG_VORBIS - { "ogg", AUDIO_FMT_OGG_VORBIS, NULL } + { "ogg", AUDIO_FMT_OGG_VORBIS, NULL }, +#endif +#ifdef CONFIG_AUDIO_FORMAT_SBC + { "sbc", AUDIO_FMT_SBC, nxplayer_getsbcsubformat } #endif }; @@ -133,6 +139,11 @@ static const struct nxplayer_dec_ops_s g_dec_ops[] = nxplayer_parse_mp3, nxplayer_fill_common }, + { + AUDIO_FMT_SBC, + nxplayer_parse_sbc, + nxplayer_fill_common + }, { AUDIO_FMT_PCM, NULL, @@ -534,6 +545,13 @@ int nxplayer_getmp3subformat(int fd) } #endif +#ifdef CONFIG_AUDIO_FORMAT_SBC +int nxplayer_getsbcsubformat(int fd) +{ + return AUDIO_FMT_SBC; +} +#endif + /**************************************************************************** * Name: nxplayer_fmtfromextension * diff --git a/system/nxplayer/nxplayer_sbc.c b/system/nxplayer/nxplayer_sbc.c new file mode 100644 index 000000000..c3851f416 --- /dev/null +++ b/system/nxplayer/nxplayer_sbc.c @@ -0,0 +1,213 @@ +/**************************************************************************** + * apps/system/nxplayer/nxplayer_sbc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "system/nxplayer.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SBC_SYNC_WORD 0x9C +#define SBC_AM_LOUDNESS 0x00 +#define SBC_AM_SNR 0x01 +#define SBC_FRAME_HEADER_SIZE 32 + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * SBC frame header + * syncword 8 BsMsbf + * sampling_frequency 2 UiMsbf + * blocks 2 UiMsbf + * channel_mode 2 UiMsbf + * allocation_method 1 UiMsbf + * subbands 1 UiMsbf + * bitpool 8 UiMsbf + * crc_check 8 UiMsbf + ****************************************************************************/ + +struct sbc_frame_header +{ + uint8_t syncword; + uint32_t sampling_frequency; + uint8_t blocks; + uint8_t nchannels; + uint8_t allocation_method; + uint8_t subbands; + uint8_t bitpool; + uint8_t crc_check; + uint8_t reserve; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * SBC header bits define + ****************************************************************************/ + +/**************************************************************************** + * sampling_frequency + * bits rate(HZ) + * 00 16000 + * 01 32000 + * 10 44100 + * 11 48000 + ****************************************************************************/ + +static const uint32_t g_sampling_freq[4] = +{ + 16000, 32000, 44100, 48000 +}; + +/**************************************************************************** + * blocks + * bits nrof_blocks + * 00 4 + * 01 8 + * 10 12 + * 11 16 + ****************************************************************************/ + +static const uint8_t g_nblocks[4] = +{ + 4, 8, 12, 16 +}; + +/**************************************************************************** + * channel mode + * bits channel mode channel numbers + * 00 MONO 1 + * 01 DUAL_CHANNEL 2 + * 10 STEREO 2 + * 11 JOINT_STEREO 2 + ****************************************************************************/ + +static const uint8_t g_nchannels[4] = +{ + 1, 2, 2, 2 +}; + +/**************************************************************************** + * allocation_method + * bits allocation_method + * 0 LOUDNESS + * 1 SNR + ****************************************************************************/ + +static const uint8_t g_allocation_method[2] = +{ + SBC_AM_LOUDNESS, SBC_AM_SNR +}; + +/**************************************************************************** + * subbands + * bits nrof_subbands + * 0 4 + * 1 8 + ****************************************************************************/ + +static const uint8_t g_nsubbands[2] = +{ + 4, 8 +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void init_sbc_frame_header(FAR struct sbc_frame_header *sbc, + FAR char *buffer) +{ + sbc->syncword = buffer[0]; + sbc->sampling_frequency = g_sampling_freq[buffer[1] >> 6]; + sbc->blocks = g_nblocks[buffer[1] >> 4 & 0x03]; + sbc->nchannels = g_nchannels[buffer[1] >> 2 & 0x03]; + sbc->allocation_method = g_allocation_method[buffer[1] >> 1 & 0x01]; + sbc->subbands = g_nsubbands[buffer[1] & 0x01]; + sbc->bitpool = buffer[2]; + sbc->crc_check = buffer[3]; + sbc->reserve = 0; +} + +static int check_sbc_frame_header_info(FAR struct sbc_frame_header *sbc) +{ + if (sbc->syncword != SBC_SYNC_WORD) + { + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nxplayer_parse_sbc + * + * nxplayer_parse_sbc() parse sbc header, get samplerate, channels, bps. + * + ****************************************************************************/ + +int nxplayer_parse_sbc(int fd, FAR uint32_t *samplerate, + FAR uint8_t *chans, FAR uint8_t *bps) +{ + char buffer[SBC_FRAME_HEADER_SIZE]; + struct sbc_frame_header sbc; + int ret = OK; + + ret = read(fd, buffer, SBC_FRAME_HEADER_SIZE); + if (ret < SBC_FRAME_HEADER_SIZE) + { + return -EINVAL; + } + + init_sbc_frame_header(&sbc, buffer); + ret = check_sbc_frame_header_info(&sbc); + if (ret < 0) + { + return ret; + } + + *samplerate = sbc.sampling_frequency; + *chans = sbc.nchannels; + *bps = 16; + lseek(fd, 0, SEEK_SET); + + return ret; +}