Skip to content

Commit

Permalink
audioutils/fmsynth: Add FM synthesizer library
Browse files Browse the repository at this point in the history
Add simple FM synthesizer library in audioutils.

(cherry picked from commit 40c506f)
  • Loading branch information
SPRESENSE committed Dec 1, 2022
1 parent c2deb79 commit d0768d9
Show file tree
Hide file tree
Showing 16 changed files with 2,211 additions and 0 deletions.
10 changes: 10 additions & 0 deletions audioutils/fmsynth/Kconfig
@@ -0,0 +1,10 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#

config AUDIOUTILS_FMSYNTH_LIB
bool "FM Synthesizer Library"
default n
---help---
Enable support for the FM Synthesizer library.
23 changes: 23 additions & 0 deletions audioutils/fmsynth/Make.defs
@@ -0,0 +1,23 @@
############################################################################
# apps/audioutils/fmsynth/Make.defs
#
# 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.
#
############################################################################

ifeq ($(CONFIG_AUDIOUTILS_FMSYNTH_LIB),y)
CONFIGURED_APPS += $(APPDIR)/audioutils/fmsynth
endif
25 changes: 25 additions & 0 deletions audioutils/fmsynth/Makefile
@@ -0,0 +1,25 @@
############################################################################
# apps/audioutils/fmsynth/Makefile
#
# 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.
#
############################################################################

include $(APPDIR)/Make.defs

CSRCS = fmsynth.c fmsynth_eg.c fmsynth_op.c

include $(APPDIR)/Application.mk
237 changes: 237 additions & 0 deletions audioutils/fmsynth/fmsynth.c
@@ -0,0 +1,237 @@
/****************************************************************************
* apps/audioutils/fmsynth/fmsynth.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 <stdlib.h>
#include <audioutils/fmsynth.h>

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define WRAP_ROUND_TIME_SEC (10)

/****************************************************************************
* Private Data
****************************************************************************/

static int max_phase_time;

/****************************************************************************
* Private Functions
****************************************************************************/

/****************************************************************************
* name: fetch_feedback
****************************************************************************/

static void fetch_feedback(FAR fmsynth_op_t *ops)
{
while (ops != NULL)
{
fmsynthop_update_feedback(ops);
ops = ops->parallelop;
}
}

/****************************************************************************
* name: update_phase
****************************************************************************/

static void update_phase(FAR fmsynth_sound_t *snd)
{
snd->phase_time++;
if (snd->phase_time >= max_phase_time)
{
snd->phase_time = 0;
}
}

/****************************************************************************
* name: sound_modulate
****************************************************************************/

static int sound_modulate(FAR fmsynth_sound_t *snd)
{
int out = 0;
FAR fmsynth_op_t *op;

if (snd->operators == NULL)
{
return out;
}

fetch_feedback(snd->operators);

for (op = snd->operators; op != NULL; op = op->parallelop)
{
out += fmsynthop_operate(op, snd->phase_time);
}

update_phase(snd);

return out * snd->volume / FMSYNTH_MAX_VOLUME;
}

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* name: fmsynth_initialize
****************************************************************************/

int fmsynth_initialize(int fs)
{
max_phase_time = fs * WRAP_ROUND_TIME_SEC;
return fmsynthop_set_samplerate(fs);
}

/****************************************************************************
* name: fmsynthsnd_create
****************************************************************************/

FAR fmsynth_sound_t *fmsynthsnd_create(void)
{
FAR fmsynth_sound_t *ret;
ret = (FAR fmsynth_sound_t *)malloc(sizeof(fmsynth_sound_t));
if (ret)
{
ret->phase_time = 0;
ret->volume = FMSYNTH_MAX_VOLUME;
ret->operators = NULL;
ret->next_sound = NULL;
}

return ret;
}

/****************************************************************************
* name: fmsynthsnd_delete
****************************************************************************/

void fmsynthsnd_delete(FAR fmsynth_sound_t *snd)
{
if (snd != NULL)
{
free(snd);
}
}

/****************************************************************************
* name: fmsynthsnd_set_operator
****************************************************************************/

int fmsynthsnd_set_operator(FAR fmsynth_sound_t *snd, FAR fmsynth_op_t *op)
{
snd->operators = op;

return OK;
}

/****************************************************************************
* name: fmsynthsnd_set_soundfreq
****************************************************************************/

void fmsynthsnd_set_soundfreq(FAR fmsynth_sound_t *snd, float freq)
{
FAR fmsynth_op_t *op;

for (op = snd->operators; op != NULL; op = op->parallelop)
{
fmsynthop_set_soundfreq(op, freq);
fmsynthop_start(op);
}
}

/****************************************************************************
* name: fmsynthsnd_set_volume
****************************************************************************/

void fmsynthsnd_set_volume(FAR fmsynth_sound_t *snd, float vol)
{
snd->volume = vol * FMSYNTH_MAX_VOLUME;
}

/****************************************************************************
* name: fmsynthsnd_add_subsound
****************************************************************************/

int fmsynthsnd_add_subsound(FAR fmsynth_sound_t *top,
FAR fmsynth_sound_t *sub)
{
FAR fmsynth_sound_t *s = top;

if (!top || !sub)
{
return ERROR;
}

for (s = top; s->next_sound; s = s->next_sound);

s->next_sound = sub;

return OK;
}

/****************************************************************************
* name: fmsynth_rendering
****************************************************************************/

int fmsynth_rendering(FAR fmsynth_sound_t *snd,
FAR int16_t *sample, int sample_num, int chnum,
fmsynth_tickcb_t cb, unsigned long cbarg)
{
int i;
int ch;
int out;
FAR fmsynth_sound_t *itr;

for (i = 0; i < sample_num; i += chnum)
{
out = 0;
for (itr = snd; itr != NULL; itr = itr->next_sound)
{
out = out + sound_modulate(itr);
}

for (ch = 0; ch < chnum; ch++)
{
*sample++ = (int16_t)out;
}

if (cb != NULL)
{
cb(cbarg);
}
}

if (i > sample_num)
{
i -= chnum;
}

/* Return total bytes stored in the buffer */

return i * sizeof(int16_t);
}

0 comments on commit d0768d9

Please sign in to comment.