mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-07 07:23:52 +00:00
[1.36.12]
lang=hr: adjust phonemes [S tS tS; Z dZ dZ;] git-svn-id: https://espeak.svn.sourceforge.net/svnroot/espeak/trunk@173 d46cf337-b52f-0410-862d-fd96e6ae7743
This commit is contained in:
+12
-7
@@ -1,10 +1,10 @@
|
||||
# remove -fno-exceptions if it causes problems with stdio library on some platforms (ARM)
|
||||
|
||||
PREFIX=/
|
||||
BINDIR=$(PREFIX)/usr/bin
|
||||
INCDIR=$(PREFIX)/usr/include/espeak
|
||||
LIBDIR=$(PREFIX)/usr/lib
|
||||
DATADIR=$(PREFIX)/usr/share/espeak-data
|
||||
PREFIX=/usr
|
||||
BINDIR=$(PREFIX)/bin
|
||||
INCDIR=$(PREFIX)/include/espeak
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
DATADIR=$(PREFIX)/share/espeak-data
|
||||
|
||||
RELEASE = 1.36
|
||||
BIN_NAME = speak
|
||||
@@ -24,9 +24,9 @@ INSTALL = install
|
||||
LN_SF = /bin/ln -sf
|
||||
MKDIR = mkdir -p
|
||||
|
||||
#AUDIO = pulseaudio
|
||||
AUDIO = portaudio
|
||||
|
||||
#AUDIO = pulseaudio
|
||||
#AUDIO = sada
|
||||
|
||||
ifeq ($(AUDIO),pulseaudio)
|
||||
WAVE=wave_pulse.cpp
|
||||
@@ -38,9 +38,14 @@ WAVE=wave.cpp
|
||||
LIB_AUDIO=-lportaudio
|
||||
USE_AUDIO=-DUSE_PORTAUDIO
|
||||
else
|
||||
ifeq ($(AUDIO),sada)
|
||||
WAVE=wave_sada.cpp
|
||||
USE_AUDIO=-DUSE_SADA
|
||||
else
|
||||
WAVE=wave.cpp
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
speak_SOURCES = speak.cpp compiledict.cpp dictionary.cpp intonation.cpp \
|
||||
readclause.cpp setlengths.cpp numbers.cpp synth_mbrola.cpp \
|
||||
|
||||
@@ -1086,6 +1086,24 @@ void Translator::SetWordStress(char *output, unsigned int dictionary_flags, int
|
||||
|
||||
switch(langopts.stress_rule)
|
||||
{
|
||||
case 8:
|
||||
// stress on first syllable, unless it is a light syllable
|
||||
if(syllable_weight[1] > 0)
|
||||
break;
|
||||
// else drop through to case 1
|
||||
case 1:
|
||||
// stress on second syllable
|
||||
if((stressed_syllable == 0) && (vowel_count > 2))
|
||||
{
|
||||
stressed_syllable = 2;
|
||||
if(max_stress == 0)
|
||||
{
|
||||
vowel_stress[stressed_syllable] = 4;
|
||||
}
|
||||
max_stress = 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// a language with stress on penultimate vowel
|
||||
|
||||
|
||||
@@ -908,6 +908,7 @@ void Translator::CalcPitches(int clause_type)
|
||||
int count;
|
||||
int n_primary;
|
||||
int count_primary;
|
||||
PHONEME_TAB *ph;
|
||||
int ph_end=n_phoneme_list;
|
||||
|
||||
SYLLABLE syllable_tab2[N_PHONEME_LIST];
|
||||
@@ -1081,6 +1082,13 @@ void Translator::CalcPitches(int clause_type)
|
||||
p->pitch2 = x;
|
||||
}
|
||||
|
||||
if(p->tone_ph)
|
||||
{
|
||||
ph = phoneme_tab[p->tone_ph];
|
||||
x = (p->pitch1 + p->pitch2)/2;
|
||||
p->pitch2 = x + ph->end_type;
|
||||
p->pitch1 = x + ph->start_type;
|
||||
}
|
||||
|
||||
if(syl->flags & SYL_EMPHASIS)
|
||||
{
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@
|
||||
#include "translate.h"
|
||||
#include "wave.h"
|
||||
|
||||
const char *version_string = "1.36.07 25.Mar.08";
|
||||
const char *version_string = "1.36.12 10.Apr.08";
|
||||
const int version_phdata = 0x013400;
|
||||
|
||||
int option_device_number = -1;
|
||||
|
||||
+15
-1
@@ -47,6 +47,7 @@
|
||||
#define OFFSET_CYRILLIC 0x420
|
||||
#define OFFSET_DEVANAGARI 0x900
|
||||
#define OFFSET_TAMIL 0xb80
|
||||
#define OFFSET_KOREAN 0x1100
|
||||
|
||||
|
||||
static const unsigned int replace_cyrillic_latin[] =
|
||||
@@ -456,8 +457,21 @@ SetLengthMods(tr,3); // all equal
|
||||
break;
|
||||
|
||||
case L('k','o'): // Korean, TEST
|
||||
{
|
||||
static const char ko_ivowels[] = {0x63,0x64,0x67,0x68,0x6d,0x72,0x74,0x75,0}; // y and i vowels
|
||||
static const char ko_voiced[] = {0x02,0x05,0x06,0xab,0xaf,0xb7,0xbc,0}; // voiced consonants, l,m,n,N
|
||||
tr = new Translator();
|
||||
|
||||
tr->letter_bits_offset = OFFSET_KOREAN;
|
||||
memset(tr->letter_bits,0,sizeof(tr->letter_bits));
|
||||
SetLetterBitsRange(tr,LETTERGP_A,0x61,0x75);
|
||||
SetLetterBits(tr,LETTERGP_Y,ko_ivowels);
|
||||
SetLetterBits(tr,LETTERGP_G,ko_voiced);
|
||||
|
||||
tr->langopts.stress_rule = 8; // ?? 1st syllable if it is heavy, else 2nd syllable
|
||||
tr->langopts.param[LOPT_UNPRONOUNCABLE] = 1; // disable check for unpronouncable words
|
||||
tr->langopts.numbers = 0x0401;
|
||||
}
|
||||
break;
|
||||
|
||||
case L('k','u'): // Kurdish
|
||||
@@ -684,7 +698,7 @@ SetLengthMods(tr,3); // all equal
|
||||
SetupTranslator(tr,stress_lengths_ta,stress_amps_ta);
|
||||
tr->langopts.length_mods0 = tr->langopts.length_mods; // don't lengthen vowels in the last syllable
|
||||
|
||||
tr->langopts.stress_rule = 1;
|
||||
tr->langopts.stress_rule = 0;
|
||||
tr->langopts.stress_flags = 0x10004; // use 'diminished' for unstressed final syllable
|
||||
tr->letter_bits_offset = OFFSET_TAMIL;
|
||||
tr->langopts.param[LOPT_WORD_MERGE] = 1; // don't break vowels betwen words
|
||||
|
||||
Executable
+576
@@ -0,0 +1,576 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008, Sun Microsystems, Inc. *
|
||||
* eSpeak driver for Solaris Audio Device Architecture (SADA) *
|
||||
* Written by Willie Walker, based on the eSpeak PulseAudio driver *
|
||||
* from Gilles Casse *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "speech.h"
|
||||
|
||||
#ifdef USE_ASYNC
|
||||
// This source file is only used for asynchronious modes
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stropts.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/audioio.h>
|
||||
|
||||
#include "wave.h"
|
||||
#include "debug.h"
|
||||
|
||||
enum {ONE_BILLION=1000000000};
|
||||
#define SAMPLE_RATE 22050
|
||||
#define SAMPLE_SIZE 16
|
||||
|
||||
#ifdef USE_SADA
|
||||
|
||||
static t_wave_callback* my_callback_is_output_enabled=NULL;
|
||||
|
||||
static const char *sun_audio_device = "/dev/audio";
|
||||
static int sun_audio_fd = -1;
|
||||
|
||||
// The total number of 16-bit samples sent to be played via the
|
||||
// wave_write method.
|
||||
//
|
||||
static uint32_t total_samples_sent;
|
||||
|
||||
// The total number of samples sent to be played via the wave_write
|
||||
// method, but which were never played because of a call to
|
||||
// wave_close.
|
||||
//
|
||||
static uint32_t total_samples_skipped;
|
||||
|
||||
// The last known playing index after a call to wave_close.
|
||||
//
|
||||
static uint32_t last_play_position=0;
|
||||
|
||||
//>
|
||||
// wave_init
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// initializes the audio subsytem.
|
||||
//
|
||||
// GLOBALS USED/MODIFIED:
|
||||
//
|
||||
// sun_audio_fd: modified to hold the file descriptor of the opened
|
||||
// audio device.
|
||||
//
|
||||
//<wave_init
|
||||
|
||||
void wave_init() {
|
||||
ENTER("wave_init");
|
||||
|
||||
audio_info_t ainfo;
|
||||
char *audio_device = NULL;
|
||||
|
||||
audio_device = getenv("AUDIODEV");
|
||||
if (audio_device != NULL) {
|
||||
if ((sun_audio_fd = open(audio_device, O_WRONLY)) < 0) {
|
||||
SHOW("wave_init() could not open: %s (%d)\n",
|
||||
audio_device, sun_audio_fd);
|
||||
}
|
||||
}
|
||||
|
||||
if (sun_audio_fd < 0) {
|
||||
if ((sun_audio_fd = open(sun_audio_device, O_WRONLY)) < 0) {
|
||||
SHOW("wave_init() could not open: %s (%d)\n",
|
||||
sun_audio_device, sun_audio_fd);
|
||||
}
|
||||
}
|
||||
|
||||
SHOW("wave_init() sun_audio_fd: %d\n", sun_audio_fd);
|
||||
|
||||
if (sun_audio_fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo);
|
||||
SHOW("wave_init() play buffer size: %d\n", ainfo.play.buffer_size);
|
||||
ainfo.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||
ainfo.play.channels = 1;
|
||||
ainfo.play.sample_rate = SAMPLE_RATE;
|
||||
ainfo.play.precision = SAMPLE_SIZE;
|
||||
|
||||
if (ioctl(sun_audio_fd, AUDIO_SETINFO, &ainfo) == -1) {
|
||||
SHOW("wave_init() failed to set audio params: %s\n", strerror(errno));
|
||||
close(sun_audio_fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_open
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// opens the audio subsystem given a specific API (e.g., "alsa",
|
||||
// "oss", ...). We ignore the_api and just return the sun_audio_fd we
|
||||
// opened in wave_init. This return value will be passed in as the
|
||||
// theHandler parameter in all other methods.
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// the_api: "alsa", "oss" (ignored)
|
||||
//
|
||||
// GLOBALS USED/MODIFIED:
|
||||
//
|
||||
// sun_audio_fd: used as return value
|
||||
//
|
||||
// RETURNS:
|
||||
//
|
||||
// sun_audio_fd opened in wave_init, which is passed in as theHandler
|
||||
// parameter in all other methods
|
||||
//
|
||||
//<wave_open
|
||||
|
||||
void* wave_open(const char* the_api)
|
||||
{
|
||||
ENTER("wave_open");
|
||||
return((void*) sun_audio_fd);
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_write
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Meant to be asynchronous, it supplies the wave sample to the lower
|
||||
// audio layer and returns. The sample is played later on. [[[WDW -
|
||||
// we purposely do not open the audio device as non-blocking because
|
||||
// managing that would be a pain. So, we rely a lot upon fifo.cpp and
|
||||
// event.cpp to not overload us, allowing us to get away with a
|
||||
// blocking write. event.cpp:polling_thread in particular appears to
|
||||
// use get_remaining_time to prevent flooding.]]]
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// theHandler: the audio device file descriptor
|
||||
// theMono16BitsWaveBuffer: the audio data
|
||||
// theSize: the number of bytes (not 16-bit samples)
|
||||
//
|
||||
// GLOBALS USED/MODIFIED:
|
||||
//
|
||||
// total_samples_sent: modified based upon 16-bit samples sent
|
||||
//
|
||||
// RETURNS:
|
||||
//
|
||||
// the number of bytes (not 16-bit samples) sent
|
||||
//
|
||||
//<wave_write
|
||||
|
||||
size_t wave_write(void* theHandler,
|
||||
char* theMono16BitsWaveBuffer,
|
||||
size_t theSize)
|
||||
{
|
||||
size_t num;
|
||||
ENTER("wave_write");
|
||||
if (my_callback_is_output_enabled && (0==my_callback_is_output_enabled())) {
|
||||
SHOW_TIME("wave_write > my_callback_is_output_enabled: no!");
|
||||
return 0;
|
||||
}
|
||||
num = write((int) theHandler, theMono16BitsWaveBuffer, theSize);
|
||||
|
||||
// Keep track of the total number of samples sent -- we use this in
|
||||
// wave_get_read_position and also use it to help calculate the
|
||||
// total_samples_skipped in wave_close.
|
||||
//
|
||||
total_samples_sent += num / 2;
|
||||
|
||||
if (num < theSize) {
|
||||
SHOW("ERROR: wave_write only wrote %d of %d bytes\n", num, theSize);
|
||||
} else {
|
||||
SHOW("wave_write wrote %d bytes\n", theSize);
|
||||
}
|
||||
|
||||
SHOW_TIME("wave_write > LEAVE");
|
||||
return num;
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_close
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Does what SADA normally would call a flush, which means to cease
|
||||
// all audio production in progress and throw any remaining audio
|
||||
// away. [[[WDW - see comment in wave_flush.]]]
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// theHandler: the audio device file descriptor
|
||||
//
|
||||
// GLOBALS USED/MODIFIED:
|
||||
//
|
||||
// last_play_position: modified to reflect play position the last time
|
||||
// this method was called
|
||||
// total_samples_sent: used to help calculate total_samples_skipped
|
||||
// total_samples_skipped: modified to hold the total number of 16-bit
|
||||
// samples sent to wave_write, but which were
|
||||
// never played
|
||||
// sun_audio_fd: used because some calls to wave_close seem to
|
||||
// pass a NULL for theHandler for some odd reason
|
||||
//
|
||||
// RETURNS:
|
||||
//
|
||||
// The result of the ioctl call (non-0 means failure)
|
||||
//
|
||||
//<wave_close
|
||||
|
||||
int wave_close(void* theHandler)
|
||||
{
|
||||
int ret;
|
||||
audio_info_t ainfo;
|
||||
int audio_fd = (int) theHandler;
|
||||
if (!audio_fd) {
|
||||
audio_fd = sun_audio_fd;
|
||||
}
|
||||
ENTER("wave_close");
|
||||
// [[[WDW: maybe do a pause/resume ioctl???]]]
|
||||
ret = ioctl(audio_fd, I_FLUSH, FLUSHRW);
|
||||
ioctl(audio_fd, AUDIO_GETINFO, &ainfo);
|
||||
|
||||
// Calculate the number of samples that won't get
|
||||
// played. We also keep track of the last_play_position
|
||||
// because wave_close can be called multiple times
|
||||
// before another call to wave_write.
|
||||
//
|
||||
if (last_play_position != ainfo.play.samples) {
|
||||
last_play_position = ainfo.play.samples;
|
||||
total_samples_skipped = total_samples_sent - last_play_position;
|
||||
}
|
||||
SHOW_TIME("wave_close > LEAVE");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_is_busy
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Returns a non-0 value if audio is being played.
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// theHandler: the audio device file descriptor
|
||||
//
|
||||
// GLOBALS USED/MODIFIED:
|
||||
//
|
||||
// sun_audio_fd: used because some calls to wave_is_busy seem to
|
||||
// pass a NULL for theHandler for some odd reason
|
||||
//
|
||||
// RETURNS:
|
||||
//
|
||||
// A non-0 value if audio is being played
|
||||
//
|
||||
//<wave_is_busy
|
||||
|
||||
int wave_is_busy(void* theHandler)
|
||||
{
|
||||
audio_info_t ainfo;
|
||||
int audio_fd = (int) theHandler;
|
||||
if (!audio_fd) {
|
||||
audio_fd = sun_audio_fd;
|
||||
}
|
||||
ENTER("wave_is_busy");
|
||||
ioctl(audio_fd, AUDIO_GETINFO, &ainfo);
|
||||
SHOW("wave_is_busy: active=%d", ainfo.play.active);
|
||||
SHOW_TIME("wave_is_busy > LEAVE");
|
||||
return ainfo.play.active;
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_terminate
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Used to end our session with eSpeak.
|
||||
//
|
||||
// GLOBALS USED/MODIFIED:
|
||||
//
|
||||
// sun_audio_fd: modified - closed and set to -1
|
||||
//
|
||||
//<wave_terminate
|
||||
|
||||
void wave_terminate()
|
||||
{
|
||||
ENTER("wave_terminate");
|
||||
close(sun_audio_fd);
|
||||
sun_audio_fd = -1;
|
||||
SHOW_TIME("wave_terminate > LEAVE");
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_flush
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Appears to want to tell the audio subsystem to make sure it plays
|
||||
// the audio. In our case, the system is already doing this, so this
|
||||
// is basically a no-op. [[[WDW - if you do a drain, you block, so
|
||||
// don't do that. In addition the typical SADA notion of flush is
|
||||
// currently handled by wave_close. I think this is most likely just
|
||||
// terminology conflict between eSpeak and SADA.]]]
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// theHandler: the audio device file descriptor
|
||||
//
|
||||
//<wave_flush
|
||||
|
||||
void wave_flush(void* theHandler)
|
||||
{
|
||||
ENTER("wave_flush");
|
||||
//ioctl((int) theHandler, AUDIO_DRAIN, 0);
|
||||
SHOW_TIME("wave_flush > LEAVE");
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_set_callback_is_output_enabled
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Sets the callback to call from wave_write before it sends data to
|
||||
// be played. It helps wave_write determine if the data should be
|
||||
// thrown away or not.
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// cb: the callback to call from wave_write
|
||||
//
|
||||
//<wave_set_callback_is_output_enabled
|
||||
|
||||
void wave_set_callback_is_output_enabled(t_wave_callback* cb)
|
||||
{
|
||||
my_callback_is_output_enabled = cb;
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_test_get_write_buffer
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Unnecessary and is used for debug output from
|
||||
// speak_lib.cpp:dispatch_audio.
|
||||
//
|
||||
// RETURNS:
|
||||
//
|
||||
// NULL
|
||||
//
|
||||
//<wave_test_get_write_buffer
|
||||
|
||||
void *wave_test_get_write_buffer()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_get_read_position
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Concerns the sample which is currently played by the audio layer,
|
||||
// where 'sample' is a small buffer of synthesized wave data,
|
||||
// identified so that the user callback could be called when the
|
||||
// 'sample' is really played. The identifier is returned by
|
||||
// wave_get_write_position. This method is unused.
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// theHandler: the audio device file descriptor
|
||||
//
|
||||
// RETURNS:
|
||||
//
|
||||
// The total number of 16-bit samples played by the audio system
|
||||
// so far.
|
||||
//
|
||||
//<wave_get_read_position
|
||||
|
||||
uint32_t wave_get_read_position(void* theHandler)
|
||||
{
|
||||
audio_info_t ainfo;
|
||||
ENTER("wave_get_read_position");
|
||||
ioctl((int) theHandler, AUDIO_GETINFO, &ainfo);
|
||||
SHOW("wave_get_read_position: %d\n", ainfo.play.samples);
|
||||
SHOW_TIME("wave_get_read_position > LEAVE");
|
||||
return ainfo.play.samples;
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_get_write_position
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Returns an identifier for a new sample, where 'sample' is a small
|
||||
// buffer of synthesized wave data, identified so that the user
|
||||
// callback could be called when the 'sample' is really played. This
|
||||
// implementation views the audio as one long continuous stream of
|
||||
// 16-bit samples.
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// theHandler: the audio device file descriptor
|
||||
//
|
||||
// GLOBALS USED/MODIFIED:
|
||||
//
|
||||
// total_samples_sent: used as the return value
|
||||
//
|
||||
// RETURNS:
|
||||
//
|
||||
// total_samples_sent, which is the index for the end of this long
|
||||
// continuous stream. [[[WDW: with a unit32_t managing 16-bit
|
||||
// samples at 22050Hz, we have about 54 hours of play time before
|
||||
// the index wraps back to 0. We don't handle that wrapping, so
|
||||
// the behavior after 54 hours of play time is undefined.]]]
|
||||
//
|
||||
//<wave_get_write_position
|
||||
|
||||
uint32_t wave_get_write_position(void* theHandler)
|
||||
{
|
||||
ENTER("wave_get_write_position");
|
||||
SHOW("wave_get_write_position: %d\n", total_samples_sent);
|
||||
SHOW_TIME("wave_get_write_position > LEAVE");
|
||||
return total_samples_sent;
|
||||
}
|
||||
|
||||
//>
|
||||
// wave_get_remaining_time
|
||||
//
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// Returns the remaining time (in ms) before the sample is played.
|
||||
// The sample in this case is a return value from a previous call to
|
||||
// wave_get_write_position.
|
||||
//
|
||||
// PARAMETERS:
|
||||
//
|
||||
// sample: an index returned from wave_get_write_position representing
|
||||
// an index into the long continuous stream of 16-bit samples
|
||||
// time: a return value representing the delay in milliseconds until
|
||||
// sample is played. A value of 0 means the sample is either
|
||||
// currently being played or it has already been played.
|
||||
//
|
||||
// GLOBALS USED/MODIFIED:
|
||||
//
|
||||
// sun_audio_fd: used to determine total number of samples played by
|
||||
// the audio system
|
||||
// total_samples_skipped: used in remaining time calculation
|
||||
//
|
||||
// RETURNS:
|
||||
//
|
||||
// Time in milliseconds before the sample is played or 0 if the sample
|
||||
// is currently playing or has already been played.
|
||||
//
|
||||
//<wave_get_remaining_time
|
||||
|
||||
int wave_get_remaining_time(uint32_t sample, uint32_t* time)
|
||||
{
|
||||
uint32_t a_time=0;
|
||||
uint32_t actual_index;
|
||||
|
||||
audio_info_t ainfo;
|
||||
ENTER("wave_get_remaining_time");
|
||||
if (!time) {
|
||||
return(-1);
|
||||
SHOW_TIME("wave_get_remaining_time > LEAVE");
|
||||
}
|
||||
|
||||
ioctl(sun_audio_fd, AUDIO_GETINFO, &ainfo);
|
||||
|
||||
// See if this sample has already been played or is currently
|
||||
// playing.
|
||||
//
|
||||
actual_index = sample - total_samples_skipped;
|
||||
if ((sample < total_samples_skipped) ||
|
||||
(actual_index <= ainfo.play.samples)) {
|
||||
*time = 0;
|
||||
} else {
|
||||
a_time = ((actual_index - ainfo.play.samples) * 1000) / SAMPLE_RATE;
|
||||
*time = (uint32_t) a_time;
|
||||
}
|
||||
SHOW("wave_get_remaining_time for %d: %d\n", sample, *time);
|
||||
SHOW_TIME("wave_get_remaining_time > LEAVE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
// notdef USE_SADA
|
||||
|
||||
void wave_init() {}
|
||||
void* wave_open(const char* the_api) {return (void *)1;}
|
||||
size_t wave_write(void* theHandler, char* theMono16BitsWaveBuffer, size_t theSize) {return theSize;}
|
||||
int wave_close(void* theHandler) {return 0;}
|
||||
int wave_is_busy(void* theHandler) {return 0;}
|
||||
void wave_terminate() {}
|
||||
uint32_t wave_get_read_position(void* theHandler) {return 0;}
|
||||
uint32_t wave_get_write_position(void* theHandler) {return 0;}
|
||||
void wave_flush(void* theHandler) {}
|
||||
typedef int (t_wave_callback)(void);
|
||||
void wave_set_callback_is_output_enabled(t_wave_callback* cb) {}
|
||||
extern void* wave_test_get_write_buffer() {return NULL;}
|
||||
|
||||
int wave_get_remaining_time(uint32_t sample, uint32_t* time)
|
||||
{
|
||||
if (!time) return(-1);
|
||||
*time = (uint32_t)0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // of USE_PORTAUDIO
|
||||
|
||||
//>
|
||||
//<clock_gettime2, add_time_in_ms
|
||||
|
||||
void clock_gettime2(struct timespec *ts)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
if (!ts)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
assert (gettimeofday(&tv, NULL) != -1);
|
||||
ts->tv_sec = tv.tv_sec;
|
||||
ts->tv_nsec = tv.tv_usec*1000;
|
||||
}
|
||||
|
||||
void add_time_in_ms(struct timespec *ts, int time_in_ms)
|
||||
{
|
||||
if (!ts)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t t_ns = (uint64_t)ts->tv_nsec + 1000000 * (uint64_t)time_in_ms;
|
||||
while(t_ns >= ONE_BILLION)
|
||||
{
|
||||
SHOW("event > add_time_in_ms ns: %d sec %Lu nsec \n", ts->tv_sec, t_ns);
|
||||
ts->tv_sec += 1;
|
||||
t_ns -= ONE_BILLION;
|
||||
}
|
||||
ts->tv_nsec = (long int)t_ns;
|
||||
}
|
||||
|
||||
#endif // USE_ASYNC
|
||||
|
||||
//>
|
||||
Reference in New Issue
Block a user