Listing all devices open AL does not work - c++

I have found some examples that claims to list all output devices for audio using openAL, however I can only get them to list the currently selected device on OSX (Yosemite, Maverick). I am using a mac and have the default sound card (Built-in Output) as well as an airplay device and some sound flower devices.
(Note: On windows it lists all devices)
I am expecting s = (char *)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); to list at least the default card and the sound flower devices. It returns nothing.
s = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER); Returns the currently selected device.
Maybe there is some issue with the devices being virtual? however, selecting soundflower from mac settings as default output first make it show up instead o "Built-in Output". We also tried with an external DAC and got the same behaviour.
list of all available output devices: Built-in Output
list of all available input devices: Built-in Microphone
default output device: Built-in Output
default input device: Built-in Microphone
...
Here is the code:
#ifdef __APPLE__
# include <OpenAL/al.h>
# include <OpenAL/alc.h>
#else
# include <AL/al.h>
# include <AL/alc.h>
# include <AL/alext.h>
#endif
#ifndef AL_VERSION_1_1
# ifdef __APPLE__
# include <OpenAL/altypes.h>
# include <OpenAL/alctypes.h>
#else
# include <AL/altypes.h>
# include <AL/alctypes.h>
# endif
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <string>
using std::string;
#ifndef ALC_ALL_DEVICES_SPECIFIER
# define ALC_ALL_DEVICES_SPECIFIER 0x1013
#endif
#define MAX_DATA 16
static const int indentation = 4;
static const int maxmimumWidth = 79;
void printExtensions (const char *, char, const char *);
void displayDevices(const char *, const char *);
char *getDeviceName(int, char **);
void testForError(void *, const string&);
void testForALCError(ALCdevice *);
int main(int argc, char **argv)
{
ALCint data[MAX_DATA];
ALCdevice *device = NULL;
ALCcontext *context = NULL;
ALenum error;
char *s;
if (alcIsExtensionPresent(NULL, "ALC_enumeration_EXT") == AL_TRUE)
{
if (alcIsExtensionPresent(NULL, "ALC_enumerate_all_EXT") == AL_FALSE)
s = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
else
s = (char *)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
displayDevices("output", s);
s = (char *)alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
displayDevices("input", s);
}
s = getDeviceName(argc, argv);
device = alcOpenDevice(s);
testForError(device, "Audio device not available.");
context = alcCreateContext(device, NULL);
testForError(context, "Unable to create a valid context.");
alcMakeContextCurrent(context);
testForALCError(device);
s = (char *)alcGetString(device, ALC_DEFAULT_DEVICE_SPECIFIER);
printf("default output device: %s\n", s);
testForALCError(device);
error = alcIsExtensionPresent(device, "ALC_EXT_capture");
if (error)
{
s = (char *)alcGetString(device, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
printf("default input device: %s\n", s);
testForALCError(device);
}
printf("capture support: %s\n", (error) ? "yes" : "no");
alcGetIntegerv(device, ALC_FREQUENCY, 1, data);
printf("mixer frequency: %u hz\n", data[0]);
testForALCError(device);
alcGetIntegerv(device, ALC_REFRESH, 1, data+1);
printf("refresh rate : %u hz\n", data[0]/data[1]);
testForALCError(device);
data[0] = 0;
alcGetIntegerv(device, ALC_MONO_SOURCES, 1, data);
error = alcGetError(device);
if (error == AL_NONE) {
printf("supported sources; mono: %u, ", data[0]);
data[0] = 0;
alcGetIntegerv(device, ALC_STEREO_SOURCES, 1, data);
printf("stereo: %u\n", data[0]);
testForALCError(device);
}
printf("ALC version: ");
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, data);
printf("%i.", *data);
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, data);
printf("%i\n", *data);
testForALCError(device);
s = (char *)alcGetString(device, ALC_EXTENSIONS);
printExtensions ("ALC extensions", ' ', s);
testForALCError(device);
s = (char *)alGetString(AL_VENDOR);
error = alGetError();
if ((error = alGetError()) != AL_NO_ERROR)
printf("Error #%x: %s\n", error, alGetString(error));
else
printf("OpenAL vendor string: %s\n", s);
s = (char *)alGetString(AL_RENDERER);
if ((error = alGetError()) != AL_NO_ERROR)
printf("Error #%x: %s\n", error, alGetString(error));
else
printf("OpenAL renderer string: %s\n", s);
s = (char *)alGetString(AL_VERSION);
if ((error = alGetError()) != AL_NO_ERROR)
printf("Error #%x: %s\n", error, alGetString(error));
else if (!s)
printf("Quering AL_VERSION returned NULL pointer!\n");
else
printf("OpenAL version string: %s\n", s);
s = (char *)alGetString(AL_EXTENSIONS);
printExtensions ("OpenAL extensions", ' ', s);
testForALCError(device);
/* alut testing mechanism */
context = alcGetCurrentContext();
if (context == NULL)
{
printf("Error: no current context\n");
}
else
{
if (alGetError () != AL_NO_ERROR)
{
printf("Alert: AL error on entry\n");
}
else
{
if (alcGetError (alcGetContextsDevice (context)) != ALC_NO_ERROR)
{
printf("Alert: ALC error on entry\n");
}
}
}
/* end of alut test */
if (alcMakeContextCurrent(NULL) == 0)
printf("alcMakeContextCurrent failed.\n");
device = alcGetContextsDevice(context);
alcDestroyContext(context);
testForALCError(device);
if (alcCloseDevice(device) == 0)
printf("alcCloseDevice failed.\n");
return 0;
}
/* -------------------------------------------------------------------------- */
void
printChar (int c, int *width)
{
putchar (c);
*width = (c == '\n') ? 0 : (*width + 1);
}
void
indent (int *width)
{
int i;
for (i = 0; i < indentation; i++)
{
printChar (' ', width);
}
}
void
printExtensions (const char *header, char separator, const char *extensions)
{
int width = 0, start = 0, end = 0;
printf ("%s:\n", header);
if (extensions == NULL || extensions[0] == '\0')
{
return;
}
indent (&width);
while (1)
{
if (extensions[end] == separator || extensions[end] == '\0')
{
if (width + end - start + 2 > maxmimumWidth)
{
printChar ('\n', &width);
indent (&width);
}
while (start < end)
{
printChar (extensions[start], &width);
start++;
}
if (extensions[end] == '\0')
{
break;
}
start++;
end++;
if (extensions[end] == '\0')
{
break;
}
printChar (',', &width);
printChar (' ', &width);
}
end++;
}
printChar ('\n', &width);
}
char *
getCommandLineOption(int argc, char **argv, const string& option)
{
int slen = option.size();
char *rv = 0;
int i;
for (i=0; i<argc; i++)
{
if (strncmp(argv[i], option.c_str(), slen) == 0)
{
i++;
if (i<argc) rv = argv[i];
}
}
return rv;
}
char *
getDeviceName(int argc, char **argv)
{
static char devname[255];
int len = 255;
char *s;
s = getCommandLineOption(argc, argv, "-d");
if (s)
{
strncpy((char *)&devname, s, len);
len -= strlen(s);
s = getCommandLineOption(argc, argv, "-r");
if (s)
{
strncat((char *)&devname, " on ", len);
len -= 4;
strncat((char *)&devname, s, len);
}
s = (char *)&devname;
}
return s;
}
void
displayDevices(const char *type, const char *list)
{
ALCchar *ptr, *nptr;
ptr = (ALCchar *)list;
printf("list of all available %s devices:\n", type);
if (!list)
{
printf("none\n");
}
else
{
nptr = ptr;
while (*(nptr += strlen(ptr)+1) != 0)
{
printf(" %s\n", ptr);
ptr = nptr;
}
printf(" %s\n", ptr);
}
}
void
testForError(void *p, const string& s)
{
if (p == NULL)
{
printf("\nError: %s\n\n", s.c_str());
exit(-1);
}
}
void
testForALCError(ALCdevice *device)
{
ALenum error;
error = alcGetError(device);
if (error != ALC_NO_ERROR)
printf("\nALC Error %x occurred: %s\n", error, alcGetString(device, error));
}

Just to give you ammunition ... here I compiled your above code and give its console output as executed on linux ubuntu 14.04 g++ (Ubuntu 4.9.1-16ubuntu6) 4.9.1
g++ -o openal_list_audio_devices openal_list_audio_devices.cpp -lopenal
stens#kamchatka ~/Dropbox/Documents/code/c++ λ
stens#kamchatka ~/Dropbox/Documents/code/c++ λ ./openal_list_audio_devices
list of all available output devices:
Built-in Audio Analog Stereo
list of all available input devices:
Built-in Audio Analog Stereo
Monitor of Built-in Audio Analog Stereo
default output device: OpenAL Soft
default input device: Built-in Audio Analog Stereo
capture support: yes
mixer frequency: 44100 hz
refresh rate : 1025 hz
supported sources; mono: 255, stereo: 1
ALC version: 1.1
ALC extensions:
ALC_ENUMERATE_ALL_EXT, ALC_ENUMERATION_EXT, ALC_EXT_CAPTURE,
ALC_EXT_DEDICATED, ALC_EXT_disconnect, ALC_EXT_EFX,
ALC_EXT_thread_local_context, ALC_SOFT_loopback
OpenAL vendor string: OpenAL Community
OpenAL renderer string: OpenAL Soft
OpenAL version string: 1.1 ALSOFT 1.15.1
OpenAL extensions:
AL_EXT_ALAW, AL_EXT_DOUBLE, AL_EXT_EXPONENT_DISTANCE, AL_EXT_FLOAT32,
AL_EXT_IMA4, AL_EXT_LINEAR_DISTANCE, AL_EXT_MCFORMATS, AL_EXT_MULAW,
AL_EXT_MULAW_MCFORMATS, AL_EXT_OFFSET, AL_EXT_source_distance_model,
AL_LOKI_quadriphonic, AL_SOFT_buffer_samples, AL_SOFT_buffer_sub_data,
AL_SOFTX_deferred_updates, AL_SOFT_direct_channels, AL_SOFT_loop_points,
AL_SOFT_source_latency

Related

config.h: No such file or directory in ssh_client from libssh's example

When I compile ssh_client code from example folder of libssh source directory( I have wrote about building process of this library in this link : libssh's functions couldn't be found on qt):
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PTY_H
#include <pty.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include "examples_common.h"
#define MAXCMD 10
static char *host = NULL;
static char *user = NULL;
static char *cmds[MAXCMD];
static char *config_file = NULL;
static struct termios terminal;
static char *pcap_file = NULL;
static char *proxycommand;
static int auth_callback(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata)
{
(void) verify;
(void) userdata;
return ssh_getpass(prompt, buf, len, echo, verify);
}
struct ssh_callbacks_struct cb = {
.auth_function = auth_callback,
.userdata = NULL,
};
static void add_cmd(char *cmd)
{
int n;
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
if (n == MAXCMD) {
return;
}
cmds[n] = strdup(cmd);
}
static void usage(void)
{
fprintf(stderr,
"Usage : ssh [options] [login#]hostname\n"
"sample client - libssh-%s\n"
"Options :\n"
" -l user : log in as user\n"
" -p port : connect to port\n"
" -d : use DSS to verify host public key\n"
" -r : use RSA to verify host public key\n"
" -F file : parse configuration file instead of default one\n"
#ifdef WITH_PCAP
" -P file : create a pcap debugging file\n"
#endif
#ifndef _WIN32
" -T proxycommand : command to execute as a socket proxy\n"
#endif
"\n",
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv)
{
int i;
while((i = getopt(argc,argv,"T:P:F:")) != -1) {
switch(i){
case 'P':
pcap_file = optarg;
break;
case 'F':
config_file = optarg;
break;
#ifndef _WIN32
case 'T':
proxycommand = optarg;
break;
#endif
default:
fprintf(stderr, "Unknown option %c\n", optopt);
usage();
}
}
if (optind < argc) {
host = argv[optind++];
}
while(optind < argc) {
add_cmd(argv[optind++]);
}
if (host == NULL) {
usage();
}
return 0;
}
#ifndef HAVE_CFMAKERAW
static void cfmakeraw(struct termios *termios_p)
{
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
termios_p->c_cflag &= ~(CSIZE|PARENB);
termios_p->c_cflag |= CS8;
}
#endif
static void do_cleanup(int i)
{
/* unused variable */
(void) i;
tcsetattr(0, TCSANOW, &terminal);
}
static void do_exit(int i)
{
/* unused variable */
(void) i;
do_cleanup(0);
exit(0);
}
static ssh_channel chan;
static int signal_delayed = 0;
static void sigwindowchanged(int i)
{
(void) i;
signal_delayed = 1;
}
static void setsignal(void)
{
signal(SIGWINCH, sigwindowchanged);
signal_delayed = 0;
}
static void sizechanged(void)
{
struct winsize win = {
.ws_row = 0,
};
ioctl(1, TIOCGWINSZ, &win);
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
setsignal();
}
static void select_loop(ssh_session session,ssh_channel channel)
{
ssh_connector connector_in, connector_out, connector_err;
int rc;
ssh_event event = ssh_event_new();
/* stdin */
connector_in = ssh_connector_new(session);
ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDINOUT);
ssh_connector_set_in_fd(connector_in, 0);
ssh_event_add_connector(event, connector_in);
/* stdout */
connector_out = ssh_connector_new(session);
ssh_connector_set_out_fd(connector_out, 1);
ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDINOUT);
ssh_event_add_connector(event, connector_out);
/* stderr */
connector_err = ssh_connector_new(session);
ssh_connector_set_out_fd(connector_err, 2);
ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR);
ssh_event_add_connector(event, connector_err);
while (ssh_channel_is_open(channel)) {
if (signal_delayed) {
sizechanged();
}
rc = ssh_event_dopoll(event, 60000);
if (rc == SSH_ERROR) {
fprintf(stderr, "Error in ssh_event_dopoll()\n");
break;
}
}
ssh_event_remove_connector(event, connector_in);
ssh_event_remove_connector(event, connector_out);
ssh_event_remove_connector(event, connector_err);
ssh_connector_free(connector_in);
ssh_connector_free(connector_out);
ssh_connector_free(connector_err);
ssh_event_free(event);
}
static void shell(ssh_session session)
{
ssh_channel channel;
struct termios terminal_local;
int interactive=isatty(0);
channel = ssh_channel_new(session);
if (channel == NULL) {
return;
}
if (interactive) {
tcgetattr(0, &terminal_local);
memcpy(&terminal, &terminal_local, sizeof(struct termios));
}
if (ssh_channel_open_session(channel)) {
printf("Error opening channel : %s\n", ssh_get_error(session));
ssh_channel_free(channel);
return;
}
chan = channel;
if (interactive) {
ssh_channel_request_pty(channel);
sizechanged();
}
if (ssh_channel_request_shell(channel)) {
printf("Requesting shell : %s\n", ssh_get_error(session));
ssh_channel_free(channel);
return;
}
if (interactive) {
cfmakeraw(&terminal_local);
tcsetattr(0, TCSANOW, &terminal_local);
setsignal();
}
signal(SIGTERM, do_cleanup);
select_loop(session, channel);
if (interactive) {
do_cleanup(0);
}
ssh_channel_free(channel);
}
static void batch_shell(ssh_session session)
{
ssh_channel channel;
char buffer[1024];
size_t i;
int s = 0;
for (i = 0; i < MAXCMD && cmds[i]; ++i) {
s += snprintf(buffer + s, sizeof(buffer) - s, "%s ", cmds[i]);
free(cmds[i]);
cmds[i] = NULL;
}
channel = ssh_channel_new(session);
if (channel == NULL) {
return;
}
ssh_channel_open_session(channel);
if (ssh_channel_request_exec(channel, buffer)) {
printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session));
ssh_channel_free(channel);
return;
}
select_loop(session, channel);
ssh_channel_free(channel);
}
static int client(ssh_session session)
{
int auth = 0;
char *banner;
int state;
if (user) {
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
return -1;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
return -1;
}
if (proxycommand != NULL) {
if (ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand)) {
return -1;
}
}
/* Parse configuration file if specified: The command-line options will
* overwrite items loaded from configuration file */
if (config_file != NULL) {
ssh_options_parse_config(session, config_file);
} else {
ssh_options_parse_config(session, NULL);
}
if (ssh_connect(session)) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
return -1;
}
state = verify_knownhost(session);
if (state != 0) {
return -1;
}
ssh_userauth_none(session, NULL);
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n", banner);
free(banner);
}
auth = authenticate_console(session);
if (auth != SSH_AUTH_SUCCESS) {
return -1;
}
if (cmds[0] == NULL) {
shell(session);
} else {
batch_shell(session);
}
return 0;
}
static ssh_pcap_file pcap;
static void set_pcap(ssh_session session)
{
if (pcap_file == NULL) {
return;
}
pcap = ssh_pcap_file_new();
if (pcap == NULL) {
return;
}
if (ssh_pcap_file_open(pcap, pcap_file) == SSH_ERROR) {
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap = NULL;
return;
}
ssh_set_pcap_file(session, pcap);
}
static void cleanup_pcap(void)
{
if (pcap != NULL) {
ssh_pcap_file_free(pcap);
}
pcap = NULL;
}
int main(int argc, char **argv)
{
ssh_session session;
session = ssh_new();
ssh_callbacks_init(&cb);
ssh_set_callbacks(session,&cb);
if (ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr,
"Error parsing command line: %s\n",
ssh_get_error(session));
usage();
}
opts(argc, argv);
signal(SIGTERM, do_exit);
set_pcap(session);
client(session);
ssh_disconnect(session);
ssh_free(session);
cleanup_pcap();
ssh_finalize();
return 0;
}
I got the following error:
/home/heydari.f/projects/ssh_client/ssh_client/main.c:100: error: config.h: No such file or directory
#include "config.h"
^~~~~~~~~~
Is there anything to do with configure or what?
I use Qt and my os is ubuntu 18.04.
Config headers as config.h normally aren't needed to compile a program against a library. Those are generated to compile the library, not the programs that link against them. If not, there will be lot of trouble as lots of software use them and there would be lots of collisions between them.
Being an example, it may be that it uses the config.h, but in that case I'm pretty sure you should compile with the system libssh uses to compile. (You may need to specify an option to compile examples when calling configure or specify something in DefineOptions.cmake or something in the same line.)
If you copied the sources (as it seems as the error states projects/ssh_client/) to build with Qt, you probably can remove that include unless it is a config from Qt itself.
Also, if you are compiling with Qt you surely need to install the lib and follow #Dmitry advice about -I, -L and -l flags to compiler.

FFmpeg: Parallel encoding with custom thread pool

One of the things I'm trying to achieve is parallel encoding via FFmpeg's c API. This looks to work out of the box quite nicely; however, I've changed the goal posts slightly:
In an existing application, I already have a thread pool at hand. Instead of using another thread pool via FFmpeg, I would like reuse the existing thread pool in my application. Having studied the latest FFmpeg trunk docs, it very much looks possible.
Using some FFmpeg sample code, I've created a sample application to demonstrate what I'm trying to achieve (see below). The sample app generates a video-only mpeg2 ts using the mp2v codec.
The problem I'm experiencing is that the custom 'thread_execute' or 'thread_execute2' are never invoked. This is despite the fact that the codec appears to indicate that threading is supported. Please be aware that I have not yet plumbed in the thread pool just yet. My first goal is for it to call the custom function pointer.
I've tried to get assistance on the FFmpeg mailing lists but to no avail.
#include <iostream>
#include <thread>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <cstring>
#include <future>
extern "C"
{
#include <libavutil/avassert.h>
#include <libavutil/channel_layout.h>
#include <libavutil/opt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
//#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}
#define STREAM_DURATION 1000.0
#define STREAM_FRAME_RATE 25 /* 25 images/s */
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
#define SCALE_FLAGS SWS_BICUBIC
// a wrapper around a single output AVStream
typedef struct OutputStream {
AVStream *st;
AVCodecContext *enc;
/* pts of the next frame that will be generated */
int64_t next_pts;
int samples_count;
AVFrame *frame;
AVFrame *tmp_frame;
float t, tincr, tincr2;
struct SwsContext *sws_ctx;
struct SwrContext *swr_ctx;
} OutputStream;
/////////////////////////////////////////////////////////////////////////////
// The ffmpeg variation raises compiler warnings.
char *cb_av_ts2str(char *buf, int64_t ts)
{
std::memset(buf,0,AV_TS_MAX_STRING_SIZE);
return av_ts_make_string(buf,ts);
}
/////////////////////////////////////////////////////////////////////////////
// The ffmpeg variation raises compiler warnings.
char *cb_av_ts2timestr(char *buf, int64_t ts, AVRational *tb)
{
std::memset(buf,0,sizeof(AV_TS_MAX_STRING_SIZE));
return av_ts_make_time_string(buf,ts,tb);
}
/////////////////////////////////////////////////////////////////////////////
// The ffmpeg variation raises compiler warnings.
char *cb_av_err2str(char *errbuf, size_t errbuf_size, int errnum)
{
std::memset(errbuf,0,errbuf_size);
return av_make_error_string(errbuf,errbuf_size,errnum);
}
int thread_execute(AVCodecContext* s, int (*func)(AVCodecContext *c2, void *arg2), void* arg, int* ret, int count, int size)
{
// Do it all serially for now
std::cout << "thread_execute" << std::endl;
for (int k = 0; k < count; ++k)
{
ret[k] = func(s, arg);
}
return 0;
}
int thread_execute2(AVCodecContext* s, int (*func)(AVCodecContext* c2, void* arg2, int, int), void* arg, int* ret, int count)
{
// Do it all serially for now
std::cout << "thread_execute2" << std::endl;
for (int k = 0; k < count; ++k)
{
ret[k] = func(s, arg, k, count);
}
return 0;
}
static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt)
{
char s[AV_TS_MAX_STRING_SIZE];
AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;
printf("pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
cb_av_ts2str(s,pkt->pts), cb_av_ts2timestr(s,pkt->pts, time_base),
cb_av_ts2str(s,pkt->dts), cb_av_ts2timestr(s,pkt->dts, time_base),
cb_av_ts2str(s,pkt->duration), cb_av_ts2timestr(s,pkt->duration, time_base),
pkt->stream_index);
}
static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
{
/* rescale output packet timestamp values from codec to stream timebase */
av_packet_rescale_ts(pkt, *time_base, st->time_base);
pkt->stream_index = st->index;
/* Write the compressed frame to the media file. */
log_packet(fmt_ctx, pkt);
return av_interleaved_write_frame(fmt_ctx, pkt);
}
/* Add an output stream. */
static void add_stream(OutputStream *ost, AVFormatContext *oc,
AVCodec **codec,
enum AVCodecID codec_id)
{
AVCodecContext *c;
int i;
/* find the encoder */
*codec = avcodec_find_encoder(codec_id);
if (!(*codec)) {
fprintf(stderr, "Could not find encoder for '%s'\n",
avcodec_get_name(codec_id));
exit(1);
}
ost->st = avformat_new_stream(oc, NULL);
if (!ost->st) {
fprintf(stderr, "Could not allocate stream\n");
exit(1);
}
ost->st->id = oc->nb_streams-1;
c = avcodec_alloc_context3(*codec);
if (!c) {
fprintf(stderr, "Could not alloc an encoding context\n");
exit(1);
}
ost->enc = c;
switch ((*codec)->type)
{
case AVMEDIA_TYPE_AUDIO:
c->sample_fmt = (*codec)->sample_fmts ?
(*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
c->bit_rate = 64000;
c->sample_rate = 44100;
if ((*codec)->supported_samplerates) {
c->sample_rate = (*codec)->supported_samplerates[0];
for (i = 0; (*codec)->supported_samplerates[i]; i++) {
if ((*codec)->supported_samplerates[i] == 44100)
c->sample_rate = 44100;
}
}
c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
c->channel_layout = AV_CH_LAYOUT_STEREO;
if ((*codec)->channel_layouts) {
c->channel_layout = (*codec)->channel_layouts[0];
for (i = 0; (*codec)->channel_layouts[i]; i++) {
if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO)
c->channel_layout = AV_CH_LAYOUT_STEREO;
}
}
c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
ost->st->time_base = (AVRational){ 1, c->sample_rate };
break;
case AVMEDIA_TYPE_VIDEO:
c->codec_id = codec_id;
c->bit_rate = 400000;
/* Resolution must be a multiple of two. */
c->width = 352;
c->height = 288;
/* timebase: This is the fundamental unit of time (in seconds) in terms
* of which frame timestamps are represented. For fixed-fps content,
* timebase should be 1/framerate and timestamp increments should be
* identical to 1. */
ost->st->time_base = (AVRational){ 1, STREAM_FRAME_RATE };
c->time_base = ost->st->time_base;
c->gop_size = 12; /* emit one intra frame every twelve frames at most */
c->pix_fmt = STREAM_PIX_FMT;
if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
/* just for testing, we also add B-frames */
c->max_b_frames = 2;
}
if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
/* Needed to avoid using macroblocks in which some coeffs overflow.
* This does not happen with normal video, it just happens here as
* the motion of the chroma plane does not match the luma plane. */
c->mb_decision = 2;
}
break;
default:
break;
}
if (c->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS ||
c->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS)
{
if (c->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS)
{
c->thread_type = FF_THREAD_FRAME;
}
if (c->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS)
{
c->thread_type = FF_THREAD_SLICE;
}
c->execute = &thread_execute;
c->execute2 = &thread_execute2;
c->thread_count = 4;
// NOTE: Testing opaque.
c->opaque = (void*)0xff;
}
/* Some formats want stream headers to be separate. */
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
/**************************************************************/
/* video output */
static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
{
AVFrame *picture;
int ret;
picture = av_frame_alloc();
if (!picture)
return NULL;
picture->format = pix_fmt;
picture->width = width;
picture->height = height;
/* allocate the buffers for the frame data */
ret = av_frame_get_buffer(picture, 32);
if (ret < 0) {
fprintf(stderr, "Could not allocate frame data.\n");
exit(1);
}
return picture;
}
static void open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
{
int ret;
AVCodecContext *c = ost->enc;
//AVDictionary *opt = NULL;
//av_dict_copy(&opt, opt_arg, 0);
/* open the codec */
ret = avcodec_open2(c, codec, NULL);
//av_dict_free(&opt);
if (ret < 0) {
char s[AV_ERROR_MAX_STRING_SIZE];
fprintf(stderr, "Could not open video codec: %s\n", cb_av_err2str(s,AV_ERROR_MAX_STRING_SIZE,ret));
exit(1);
}
/* allocate and init a re-usable frame */
ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);
if (!ost->frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
/* If the output format is not YUV420P, then a temporary YUV420P
* picture is needed too. It is then converted to the required
* output format. */
ost->tmp_frame = NULL;
if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);
if (!ost->tmp_frame) {
fprintf(stderr, "Could not allocate temporary picture\n");
exit(1);
}
}
/* copy the stream parameters to the muxer */
ret = avcodec_parameters_from_context(ost->st->codecpar, c);
if (ret < 0) {
fprintf(stderr, "Could not copy the stream parameters\n");
exit(1);
}
}
/* Prepare a dummy image. */
static void fill_yuv_image(AVFrame *pict, int frame_index,
int width, int height)
{
int x, y, i;
i = frame_index;
/* Y */
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
/* Cb and Cr */
for (y = 0; y < height / 2; y++) {
for (x = 0; x < width / 2; x++) {
pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
}
}
}
static AVFrame *get_video_frame(OutputStream *ost)
{
AVCodecContext *c = ost->enc;
/* check if we want to generate more frames */
if (av_compare_ts(ost->next_pts, c->time_base,
STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
return NULL;
/* when we pass a frame to the encoder, it may keep a reference to it
* internally; make sure we do not overwrite it here */
if (av_frame_make_writable(ost->frame) < 0)
exit(1);
if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
/* as we only generate a YUV420P picture, we must convert it
* to the codec pixel format if needed */
/*if (!ost->sws_ctx) {
ost->sws_ctx = sws_getContext(c->width, c->height,
AV_PIX_FMT_YUV420P,
c->width, c->height,
c->pix_fmt,
SCALE_FLAGS, NULL, NULL, NULL);
if (!ost->sws_ctx) {
fprintf(stderr,
"Could not initialize the conversion context\n");
exit(1);
}
}
fill_yuv_image(ost->tmp_frame, ost->next_pts, c->width, c->height);
sws_scale(ost->sws_ctx,
(const uint8_t * const *)ost->tmp_frame->data, ost->tmp_frame->linesize,
0, c->height, ost->frame->data, ost->frame->linesize);*/
} else {
fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height);
}
ost->frame->pts = ost->next_pts++;
return ost->frame;
}
/*
* encode one video frame and send it to the muxer
* return 1 when encoding is finished, 0 otherwise
*/
static int write_video_frame(AVFormatContext *oc, OutputStream *ost)
{
int ret;
AVCodecContext *c;
AVFrame *frame;
int got_packet = 0;
AVPacket pkt = { 0 };
c = ost->enc;
frame = get_video_frame(ost);
if (frame)
{
ret = avcodec_send_frame(ost->enc, frame);
if (ret < 0)
{
char s[AV_ERROR_MAX_STRING_SIZE];
fprintf(stderr, "Error encoding video frame: %s\n", cb_av_err2str(s, AV_ERROR_MAX_STRING_SIZE, ret));
exit(1);
}
}
av_init_packet(&pkt);
ret = avcodec_receive_packet(ost->enc,&pkt);
if (ret < 0)
{
if (ret == AVERROR(EAGAIN)) { ret = 0; }
else
{
char s[AV_ERROR_MAX_STRING_SIZE];
fprintf(stderr, "Error receiving packet: %s\n", cb_av_err2str(s,AV_ERROR_MAX_STRING_SIZE,ret));
exit(1);
}
}
else
{
got_packet = 1;
ret = write_frame(oc, &c->time_base, ost->st, &pkt);
}
if (ret < 0) {
char s[AV_ERROR_MAX_STRING_SIZE];
fprintf(stderr, "Error while writing video frame: %s\n", cb_av_err2str(s,AV_ERROR_MAX_STRING_SIZE,ret));
exit(1);
}
return (frame || got_packet) ? 0 : 1;
}
static void close_stream(AVFormatContext *oc, OutputStream *ost)
{
avcodec_free_context(&ost->enc);
av_frame_free(&ost->frame);
av_frame_free(&ost->tmp_frame);
//sws_freeContext(ost->sws_ctx);
//swr_free(&ost->swr_ctx);
}
/**************************************************************/
/* media file output */
int main(int argc, char **argv)
{
OutputStream video_st = { 0 }, audio_st = { 0 };
const char *filename;
AVOutputFormat *fmt;
AVFormatContext *oc;
AVCodec /**audio_codec,*/ *video_codec;
int ret;
int have_video = 0, have_audio = 0;
int encode_video = 0, encode_audio = 0;
AVDictionary *opt = NULL;
int i;
/* Initialize libavcodec, and register all codecs and formats. */
av_register_all();
avformat_network_init();
if (argc < 2) {
printf("usage: %s output_file\n"
"API example program to output a media file with libavformat.\n"
"This program generates a synthetic audio and video stream, encodes and\n"
"muxes them into a file named output_file.\n"
"The output format is automatically guessed according to the file extension.\n"
"Raw images can also be output by using '%%d' in the filename.\n"
"\n", argv[0]);
return 1;
}
filename = argv[1];
for (i = 2; i+1 < argc; i+=2) {
if (!strcmp(argv[i], "-flags") || !strcmp(argv[i], "-fflags"))
av_dict_set(&opt, argv[i]+1, argv[i+1], 0);
}
const char *pfilename = filename;
/* allocate the output media context */
avformat_alloc_output_context2(&oc, NULL, "mpegts", pfilename);
if (!oc) {
printf("Could not deduce output format from file extension: using MPEG.\n");
avformat_alloc_output_context2(&oc, NULL, "mpeg", pfilename);
}
if (!oc)
return 1;
fmt = oc->oformat;
/* Add the audio and video streams using the default format codecs
* and initialize the codecs. */
if (fmt->video_codec != AV_CODEC_ID_NONE) {
add_stream(&video_st, oc, &video_codec, fmt->video_codec);
have_video = 1;
encode_video = 1;
}
/*if (fmt->audio_codec != AV_CODEC_ID_NONE) {
add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec);
have_audio = 1;
encode_audio = 1;
}*/
/* Now that all the parameters are set, we can open the audio and
* video codecs and allocate the necessary encode buffers. */
if (have_video)
open_video(oc, video_codec, &video_st, opt);
//if (have_audio)
// open_audio(oc, audio_codec, &audio_st, opt);
av_dump_format(oc, 0, pfilename, 1);
/* open the output file, if needed */
if (!(fmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&oc->pb, pfilename, AVIO_FLAG_WRITE);
if (ret < 0) {
char s[AV_ERROR_MAX_STRING_SIZE];
fprintf(stderr, "Could not open '%s': %s\n", pfilename,
cb_av_err2str(s,AV_ERROR_MAX_STRING_SIZE,ret));
return 1;
}
}
/* Write the stream header, if any. */
ret = avformat_write_header(oc, &opt);
if (ret < 0) {
char s[AV_ERROR_MAX_STRING_SIZE];
fprintf(stderr, "Error occurred when opening output file: %s\n",
cb_av_err2str(s,AV_ERROR_MAX_STRING_SIZE,ret));
return 1;
}
while (encode_video || encode_audio) {
/* select the stream to encode */
if (encode_video &&
(!encode_audio || av_compare_ts(video_st.next_pts, video_st.enc->time_base,
audio_st.next_pts, audio_st.enc->time_base) <= 0)) {
encode_video = !write_video_frame(oc, &video_st);
} else {
//encode_audio = !write_audio_frame(oc, &audio_st);
}
//std::this_thread::sleep_for(std::chrono::milliseconds(35));
}
/* Write the trailer, if any. The trailer must be written before you
* close the CodecContexts open when you wrote the header; otherwise
* av_write_trailer() may try to use memory that was freed on
* av_codec_close(). */
av_write_trailer(oc);
/* Close each codec. */
if (have_video)
close_stream(oc, &video_st);
if (have_audio)
close_stream(oc, &audio_st);
if (!(fmt->flags & AVFMT_NOFILE))
/* Close the output file. */
avio_closep(&oc->pb);
/* free the stream */
avformat_free_context(oc);
return 0;
}
//
Environment:
Ubuntu Zesty (17.04)
FFmpeg version 3.2.4 (via package manager)
gcc 6.3 (C++)
You have to do following:
call avcodec_alloc_context3(...). This call will set default execute and execute2 functions in new context
set c->thread_count = number_of_threads_in_your_thread_pool()
call avcodec_open2(...).
set c->execute and c->execute2 to point to your functions
call ff_thread_free(c). This function isnt exposed in libavcodec headers but you can add following line:
extern "C" void ff_thread_free(AVCodecContext *s);
Drawback is that libavcodec will create internal thread pool after avcodec_open2(...) call, and that pool will be deleted in ff_thread_free() call.
Internal thread pool is very efficient, but its not good if you plan to do parallel encoding of multiple video feeds. In that case libavcodec will create separate thread pool for each encoding video feed.

Using iconv translit to convert from UTF-8 to CP1251

I'am trying to convert string "aÜ" from UTF-8 to CP1251 via C++ library iconv.h using TRANSLIT and as a result I get string "a?", when expecting "aU".
When I use php script <?php echo iconv("UTF-8", "Windows-1251//TRANSLIT", "Ü");> on this computer, I get "aU" string as result.
Here's the code:
#include <cstdlib>
#include <iconv.h>
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
using namespace std;
int IConvert(char *buf,char *outbuf, size_t len, const char *from, const char *to)
{
iconv_t iconv_cd;
if ((iconv_cd = iconv_open(to, from)) == (iconv_t) -1) {
printf("Cannot open iconv from %s to %s\n", from, to);
return 0;
}
char *inbuf = buf;
size_t inlen = len;
size_t outlen = len;
size_t res = 0;
while (inlen > 0 && outlen > 0) {
res = iconv(iconv_cd, &inbuf, &inlen, &outbuf, &outlen);
if (res == 0)
break;
if (res == (size_t) (-1)) {
if (errno != EILSEQ && errno != EINVAL) {
iconv_close(iconv_cd);
*outbuf = '\0';
printf("Erorr %s (%s)\n", strerror(errno), from);
return 0;
} else if (inbuf < outbuf) {
iconv_close(iconv_cd);
*outbuf = '\0';
printf("Erorr %s (inbuf < outbuf)\n", strerror(errno));
return 0;
}
}
if (inlen > 0 && outlen > 0) {
*outbuf++ = *inbuf++;
inlen--;
outlen--;
}
}
iconv_close(iconv_cd);
*outbuf = '\0';
return 1;
}
int main(int argc, char** argv) {
char* line = "\u00C0a\u00DC";
char* from = (char*) malloc(strlen(from)+1);
char* to = (char*) malloc(strlen(from)+1);
strcpy(from, line);
printf("%s\n", from);
IConvert(from, to, strlen(from)+1, "UTF-8", "CP1251//TRANSLIT");
printf("%s\n", to);
return 0;
}
Any idea what problem could be?
The solution is
setlocale(LC_ALL, "");
at the beginning of your program. Yes, the locale influences the transliteration. In a German locale Ü would be transliterated to UE not U.

Open a device by name using libftdi or libusb

I am using libftdi with multiple ftdi devices for a program running on Ubuntu 14.04. I have a udev rule that detects the devices based on a custom manufacturer string and gives them a symlink in the dev directory. It would look similar to /dev/my-device. I would like to use libftdi to open the device using this string instead of the pid/vid/serial number.
I did not see that this capability was available in libftdi so I checked libusb and didn't see that functionality either.
You could try this:
static int usbGetDescriptorString(usb_dev_handle *dev, int index, int langid, char *buf, int buflen) {
char buffer[256];
int rval, i;
// make standard request GET_DESCRIPTOR, type string and given index
// (e.g. dev->iProduct)
rval = usb_control_msg(dev,
USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid,
buffer, sizeof(buffer), 1000);
if (rval < 0) // error
return rval;
// rval should be bytes read, but buffer[0] contains the actual response size
if ((unsigned char)buffer[0] < rval)
rval = (unsigned char)buffer[0]; // string is shorter than bytes read
if (buffer[1] != USB_DT_STRING) // second byte is the data type
return 0; // invalid return type
// we're dealing with UTF-16LE here so actual chars is half of rval,
// and index 0 doesn't count
rval /= 2;
/* lossy conversion to ISO Latin1 */
for (i = 1; i < rval && i < buflen; i++) {
if (buffer[2 * i + 1] == 0)
buf[i - 1] = buffer[2 * i];
else
buf[i - 1] = '?'; /* outside of ISO Latin1 range */
}
buf[i - 1] = 0;
return i - 1;
}
static usb_dev_handle * usbOpenDevice(int vendor, char *vendorName, int product, char *productName) {
struct usb_bus *bus;
struct usb_device *dev;
char devVendor[256], devProduct[256];
usb_dev_handle * handle = NULL;
usb_init();
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
if (dev->descriptor.idVendor != vendor ||
dev->descriptor.idProduct != product)
continue;
/* we need to open the device in order to query strings */
if (!(handle = usb_open(dev))) {
fprintf(stderr, "Warning: cannot open USB device: %sn",
usb_strerror());
continue;
}
/* get vendor name */
if (usbGetDescriptorString(handle, dev->descriptor.iManufacturer, 0x0409, devVendor, sizeof(devVendor)) < 0) {
fprintf(stderr,
"Warning: cannot query manufacturer for device: %sn",
usb_strerror());
usb_close(handle);
continue;
}
/* get product name */
if (usbGetDescriptorString(handle, dev->descriptor.iProduct, 0x0409, devProduct, sizeof(devVendor)) < 0) {
fprintf(stderr,
"Warning: cannot query product for device: %sn",
usb_strerror());
usb_close(handle);
continue;
}
if (strcmp(devVendor, vendorName) == 0 &&
strcmp(devProduct, productName) == 0)
return handle;
else
usb_close(handle);
}
}
return NULL;
}

Espeak SAPI/dll usage on Windows?

Question: I am trying to use the espeak text-to-speech engine.
So for I got it working wounderfully on linux (code below).
Now I wanted to port this basic program to windows, too, but it's nearly impossible...
Part of the problem is that the windows dll only allows for AUDIO_OUTPUT_SYNCHRONOUS, which means it requires a callback, but I can't figure out how to play the audio from the callback... First it crashed, then I realized, I need a callback function, now I get the data in the callback function, but I don't know how to play it... as it is neither a wav file nor plays automatically as on Linux.
The sourceforge site is rather useless, because it basically says use the SAPI version, but then there is no example on how to use the sapi espeak dll...
Anyway, here's my code, can anybody help?
#ifdef __cplusplus
#include <cstdio>
#include <cstdlib>
#include <cstring>
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <assert.h>
#include <ctype.h>
//#include "speak_lib.h"
#include "espeak/speak_lib.h"
// libespeak-dev: /usr/include/espeak/speak_lib.h
// apt-get install libespeak-dev
// apt-get install libportaudio-dev
// g++ -o mine mine.cpp -lespeak
// g++ -o mine mine.cpp -I/usr/include/espeak/ -lespeak
// gcc -o mine mine.cpp -I/usr/include/espeak/ -lespeak
char voicename[40];
int samplerate;
int quiet = 0;
static char genders[4] = {' ','M','F',' '};
//const char *data_path = "/usr/share/"; // /usr/share/espeak-data/
const char *data_path = NULL; // use default path for espeak-data
int strrcmp(const char *s, const char *sub)
{
int slen = strlen(s);
int sublen = strlen(sub);
return memcmp(s + slen - sublen, sub, sublen);
}
char * strrcpy(char *dest, const char *source)
{
// Pre assertions
assert(dest != NULL);
assert(source != NULL);
assert(dest != source);
// tk: parentheses
while((*dest++ = *source++))
;
return(--dest);
}
const char* GetLanguageVoiceName(const char* pszShortSign)
{
#define LANGUAGE_LENGTH 30
static char szReturnValue[LANGUAGE_LENGTH] ;
memset(szReturnValue, 0, LANGUAGE_LENGTH);
for (int i = 0; pszShortSign[i] != '\0'; ++i)
szReturnValue[i] = (char) tolower(pszShortSign[i]);
const espeak_VOICE **voices;
espeak_VOICE voice_select;
voices = espeak_ListVoices(NULL);
const espeak_VOICE *v;
for(int ix=0; (v = voices[ix]) != NULL; ix++)
{
if( !strrcmp( v->languages, szReturnValue) )
{
strcpy(szReturnValue, v->name);
return szReturnValue;
}
} // End for
strcpy(szReturnValue, "default");
return szReturnValue;
} // End function getvoicename
void ListVoices()
{
const espeak_VOICE **voices;
espeak_VOICE voice_select;
voices = espeak_ListVoices(NULL);
const espeak_VOICE *v;
for(int ix=0; (v = voices[ix]) != NULL; ix++)
{
printf("Shortsign: %s\n", v->languages);
printf("age: %d\n", v->age);
printf("gender: %c\n", genders[v->gender]);
printf("name: %s\n", v->name);
printf("\n\n");
} // End for
} // End function getvoicename
int main()
{
printf("Hello World!\n");
const char* szVersionInfo = espeak_Info(NULL);
printf("Espeak version: %s\n", szVersionInfo);
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0);
strcpy(voicename, "default");
// espeak --voices
strcpy(voicename, "german");
strcpy(voicename, GetLanguageVoiceName("DE"));
if(espeak_SetVoiceByName(voicename) != EE_OK)
{
printf("Espeak setvoice error...\n");
}
static char word[200] = "Hello World" ;
strcpy(word, "TV-fäns aufgepasst, es ist 20 Uhr 15. Zeit für Rambo 3");
strcpy(word, "Unnamed Player wurde zum Opfer von GSG9");
int speed = 220;
int volume = 500; // volume in range 0-100 0=silence
int pitch = 50; // base pitch, range 0-100. 50=normal
// espeak.cpp 625
espeak_SetParameter(espeakRATE, speed, 0);
espeak_SetParameter(espeakVOLUME,volume,0);
espeak_SetParameter(espeakPITCH,pitch,0);
// espeakRANGE: pitch range, range 0-100. 0-monotone, 50=normal
// espeakPUNCTUATION: which punctuation characters to announce:
// value in espeak_PUNCT_TYPE (none, all, some),
espeak_VOICE *voice_spec = espeak_GetCurrentVoice();
voice_spec->gender=2; // 0=none 1=male, 2=female,
//voice_spec->age = age;
espeak_SetVoiceByProperties(voice_spec);
espeak_Synth( (char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
espeak_Synchronize();
strcpy(voicename, GetLanguageVoiceName("EN"));
espeak_SetVoiceByName(voicename);
strcpy(word, "Geany was fragged by GSG9 Googlebot");
strcpy(word, "Googlebot");
espeak_Synth( (char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
espeak_Synchronize();
espeak_Terminate();
printf("Espeak terminated\n");
return EXIT_SUCCESS;
}
/*
if(espeak_SetVoiceByName(voicename) != EE_OK)
{
memset(&voice_select,0,sizeof(voice_select));
voice_select.languages = voicename;
if(espeak_SetVoiceByProperties(&voice_select) != EE_OK)
{
fprintf(stderr,"%svoice '%s'\n",err_load,voicename);
exit(2);
}
}
*/
The above code is for Linux.
The below code is about as far as I got on Vista x64 (32 bit emu):
#ifdef __cplusplus
#include <cstdio>
#include <cstdlib>
#include <cstring>
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <assert.h>
#include <ctype.h>
#include "speak_lib.h"
//#include "espeak/speak_lib.h"
// libespeak-dev: /usr/include/espeak/speak_lib.h
// apt-get install libespeak-dev
// apt-get install libportaudio-dev
// g++ -o mine mine.cpp -lespeak
// g++ -o mine mine.cpp -I/usr/include/espeak/ -lespeak
// gcc -o mine mine.cpp -I/usr/include/espeak/ -lespeak
char voicename[40];
int iSampleRate;
int quiet = 0;
static char genders[4] = {' ','M','F',' '};
//const char *data_path = "/usr/share/"; // /usr/share/espeak-data/
//const char *data_path = NULL; // use default path for espeak-data
const char *data_path = "C:\\Users\\Username\\Desktop\\espeak-1.43-source\\espeak-1.43-source\\";
int strrcmp(const char *s, const char *sub)
{
int slen = strlen(s);
int sublen = strlen(sub);
return memcmp(s + slen - sublen, sub, sublen);
}
char * strrcpy(char *dest, const char *source)
{
// Pre assertions
assert(dest != NULL);
assert(source != NULL);
assert(dest != source);
// tk: parentheses
while((*dest++ = *source++))
;
return(--dest);
}
const char* GetLanguageVoiceName(const char* pszShortSign)
{
#define LANGUAGE_LENGTH 30
static char szReturnValue[LANGUAGE_LENGTH] ;
memset(szReturnValue, 0, LANGUAGE_LENGTH);
for (int i = 0; pszShortSign[i] != '\0'; ++i)
szReturnValue[i] = (char) tolower(pszShortSign[i]);
const espeak_VOICE **voices;
espeak_VOICE voice_select;
voices = espeak_ListVoices(NULL);
const espeak_VOICE *v;
for(int ix=0; (v = voices[ix]) != NULL; ix++)
{
if( !strrcmp( v->languages, szReturnValue) )
{
strcpy(szReturnValue, v->name);
return szReturnValue;
}
} // End for
strcpy(szReturnValue, "default");
return szReturnValue;
} // End function getvoicename
void ListVoices()
{
const espeak_VOICE **voices;
espeak_VOICE voice_select;
voices = espeak_ListVoices(NULL);
const espeak_VOICE *v;
for(int ix=0; (v = voices[ix]) != NULL; ix++)
{
printf("Shortsign: %s\n", v->languages);
printf("age: %d\n", v->age);
printf("gender: %c\n", genders[v->gender]);
printf("name: %s\n", v->name);
printf("\n\n");
} // End for
} // End function getvoicename
/* Callback from espeak. Directly speaks using AudioTrack. */
#define LOGI(x) printf("%s\n", x)
static int AndroidEspeakDirectSpeechCallback(short *wav, int numsamples, espeak_EVENT *events)
{
char buf[100];
sprintf(buf, "AndroidEspeakDirectSpeechCallback: %d samples", numsamples);
LOGI(buf);
if (wav == NULL)
{
LOGI("Null: speech has completed");
}
if (numsamples > 0)
{
//audout->write(wav, sizeof(short) * numsamples);
sprintf(buf, "AudioTrack wrote: %d bytes", sizeof(short) * numsamples);
LOGI(buf);
}
return 0; // continue synthesis (1 is to abort)
}
static int AndroidEspeakSynthToFileCallback(short *wav, int numsamples,espeak_EVENT *events)
{
char buf[100];
sprintf(buf, "AndroidEspeakSynthToFileCallback: %d samples", numsamples);
LOGI(buf);
if (wav == NULL)
{
LOGI("Null: speech has completed");
}
// The user data should contain the file pointer of the file to write to
//void* user_data = events->user_data;
FILE* user_data = fopen ( "myfile1.wav" , "ab" );
FILE* fp = static_cast<FILE *>(user_data);
// Write all of the samples
fwrite(wav, sizeof(short), numsamples, fp);
return 0; // continue synthesis (1 is to abort)
}
int main()
{
printf("Hello World!\n");
const char* szVersionInfo = espeak_Info(NULL);
printf("Espeak version: %s\n", szVersionInfo);
iSampleRate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 4096, data_path, 0);
if (iSampleRate <= 0)
{
printf("Unable to initialize espeak");
return EXIT_FAILURE;
}
//samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0);
//ListVoices();
strcpy(voicename, "default");
// espeak --voices
//strcpy(voicename, "german");
//strcpy(voicename, GetLanguageVoiceName("DE"));
if(espeak_SetVoiceByName(voicename) != EE_OK)
{
printf("Espeak setvoice error...\n");
}
static char word[200] = "Hello World" ;
strcpy(word, "TV-fäns aufgepasst, es ist 20 Uhr 15. Zeit für Rambo 3");
strcpy(word, "Unnamed Player wurde zum Opfer von GSG9");
int speed = 220;
int volume = 500; // volume in range 0-100 0=silence
int pitch = 50; // base pitch, range 0-100. 50=normal
// espeak.cpp 625
espeak_SetParameter(espeakRATE, speed, 0);
espeak_SetParameter(espeakVOLUME,volume,0);
espeak_SetParameter(espeakPITCH,pitch,0);
// espeakRANGE: pitch range, range 0-100. 0-monotone, 50=normal
// espeakPUNCTUATION: which punctuation characters to announce:
// value in espeak_PUNCT_TYPE (none, all, some),
//espeak_VOICE *voice_spec = espeak_GetCurrentVoice();
//voice_spec->gender=2; // 0=none 1=male, 2=female,
//voice_spec->age = age;
//espeak_SetVoiceByProperties(voice_spec);
//espeak_SetSynthCallback(AndroidEspeakDirectSpeechCallback);
espeak_SetSynthCallback(AndroidEspeakSynthToFileCallback);
unsigned int unique_identifier;
espeak_ERROR err = espeak_Synth( (char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, &unique_identifier, NULL);
err = espeak_Synchronize();
/*
strcpy(voicename, GetLanguageVoiceName("EN"));
espeak_SetVoiceByName(voicename);
strcpy(word, "Geany was fragged by GSG9 Googlebot");
strcpy(word, "Googlebot");
espeak_Synth( (char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
espeak_Synchronize();
*/
// espeak_Cancel();
espeak_Terminate();
printf("Espeak terminated\n");
system("pause");
return EXIT_SUCCESS;
}
Have you tried passing the buffer you obtain in your callback to sndplaysnd()??
Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Its standard winAPI is as follows:
sndPlaySound(buffer[0], SND_ASYNC | SND_MEMORY)
Alternately, if you have a wav-file that has the audio to play:
sndPlaySound(filename, SND_ASYNC)
playsound has a ASYNC mode that wouldn't block your program's execution while the audio is being played.
NOTE: I have used it in VB and the above snippets are for use in VB. If you are coding in VC++, you might have to modify them accordingly. But the basic intention remains the same; to pass the buffer to sndPlaySound with the ASYNC flag set.
Good LUCK!!
Several changes in source code are needed to make the windows library have the same functionality as the one on Linux. I listed the changes here. The ready to use binary is also available.
All the patches and the description were also sent to espeak maintainer (publicly, through the mailing list and patches tracker), so maybe in future it will be available directly.