Was cooking for two months, since 2014-05-11.
* t/gui_sched: (53 commits)
gui: Always initialize theme.
gui: Simplify color handling.
gui: Dont catch SIGWINCH.
gui: Call waitpid() from exec and status task.
Doxify para_gui.
gui: Speed up window refresh.
gui: Rename cmd_task to exec_task.
gui: Move static variables of cmd_post_select() into struct cmd_task.
gui: Move some variables into struct status_task.
gui: Switch to the standard paraslash scheduler.
gui: Use cpp magic to define command handlers.
gui: Execute stat command in status_post_select().
gui: Rename COMMAND/EXTERNAL/GETCH mode.
gui: Get rid of do_select()'s mode parameter and call it only once.
gui: Reorder functions.
gui: Move signal handling code out of do_select().
gui: Move input related code out of do_select().
gui: Move external command handling out of do_select().
gui: Introduce status_post_select().
gui: Improve config reload.
...
0.5.3 (to be released) "symbolic synchronization"
-------------------------------------------------
+ - para_gui has been converted to use the paraslash scheduler.
- Various alsa-related fixes, mostly for the raspberry pi.
+ - The test suite has been extended to include sanity checks
+ for the generated man pages.
+ - ao_writer fixes. This writer was in a quite bad shape. Many
+ serious bugs have been fixed.
+ - new audiod command: version.
+ - Minor improvements to the bitstream API.
+ - The cpsi command now prints a meaningful error message if
+ none of the given patterns matched any audio file.
----------------------------------------
0.5.2 (2014-04-11) "orthogonal interior"
out:
if (ret < 0)
para_printf(&cad.pb, "%s\n", para_strerror(-ret));
- else if (cad.flags & CPSI_FLAG_VERBOSE) {
- if (pmd.num_matches > 0)
+ else if (pmd.num_matches > 0) {
+ if (cad.flags & CPSI_FLAG_VERBOSE)
para_printf(&cad.pb, "copied requested afsi from %s "
"to %u files\n", source_path, pmd.num_matches);
- else
- para_printf(&cad.pb, "nothing copied\n");
- }
+ } else
+ para_printf(&cad.pb, "no matches - nothing copied\n");
if (cad.pb.offset)
pass_buffer_as_shm(fd, SBD_OUTPUT, cad.pb.buf, cad.pb.offset);
free(cad.pb.buf);
pthread_t thread;
pthread_attr_t attr;
+ /* The mutex and the condition variable serialize access to ->btrn */
pthread_mutex_t mutex;
pthread_cond_t data_available;
struct btr_node *thread_btrn;
if (!pawd)
return;
+ assert(!pawd->thread_btrn);
ao_close(pawd->dev);
free(pawd);
wn->private_data = NULL;
- ao_shutdown();
}
static void aow_pre_select(struct sched *s, struct task *t)
{
struct writer_node *wn = container_of(t, struct writer_node, task);
- int ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+ struct private_aow_data *pawd = wn->private_data;
+ int ret;
- if (ret == 0)
- return;
+ if (!pawd) { /* not yet started */
+ assert(wn->btrn);
+ ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+ if (ret != 0)
+ goto min_delay;
+ return; /* no data available */
+ }
+ if (!wn->btrn) { /* EOF */
+ if (!pawd->thread_btrn) /* ready to exit */
+ goto min_delay;
+ /* wait for the play thread to terminate */
+ goto timeout;
+ }
+ pthread_mutex_lock(&pawd->mutex);
+ ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
+ pthread_mutex_unlock(&pawd->mutex);
+ if (ret != 0)
+ goto min_delay;
+ /*
+ * Even though the node status is zero, we might have data available,
+ * but the output buffer is full. If we don't set a timeout here, we
+ * are woken up only if new data arrives, which might be too late and
+ * result in a buffer underrun in the playing thread. To avoid this we
+ * never sleep longer than the (default) buffer time.
+ */
+timeout:
+ return sched_request_timeout_ms(20, s);
+min_delay:
sched_min_delay(s);
}
struct private_aow_data *pawd = para_malloc(sizeof(*pawd));
struct ao_write_args_info *conf = wn->conf;
- ao_initialize();
if (conf->driver_given) {
ret = -E_AO_BAD_DRIVER;
id = ao_driver_id(conf->driver_arg);
char *data;
int ret;
+ pthread_mutex_lock(&pawd->mutex);
for (;;) {
- /*
- * Lock mutex and wait for signal. pthread_cond_wait() will
- * automatically and atomically unlock mutex while it waits.
- */
- pthread_mutex_lock(&pawd->mutex);
for (;;) {
ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
if (ret < 0)
- goto unlock;
+ goto fail;
if (ret > 0) {
btr_merge(btrn, wn->min_iqs);
bytes = btr_next_buffer(btrn, &data);
break;
/* eof and less than a single frame available */
ret = -E_WRITE_COMMON_EOF;
- goto unlock;
+ goto fail;
}
- //PARA_CRIT_LOG("waiting for data\n");
- //usleep(1000);
- //pthread_mutex_unlock(&pawd->mutex);
- pthread_cond_wait(&pawd->data_available, &pawd->mutex);
+ /*
+ * No data available, go to sleep and wait for the main
+ * thread to wake us up. pthread_cond_wait() unlocks
+ * the mutex while it waits and locks it again upon
+ * return.
+ */
+ ret = pthread_cond_wait(&pawd->data_available,
+ &pawd->mutex);
+ /* pthread_cond_wait() can never fail here */
+ assert(ret == 0);
}
- pthread_mutex_unlock(&pawd->mutex);
assert(frames > 0);
bytes = frames * pawd->bytes_per_frame;
- ret = -E_AO_PLAY;
- if (ao_play(pawd->dev, data, bytes) == 0) /* failure */
- goto out;
+ pthread_mutex_unlock(&pawd->mutex);
+ ret = ao_play(pawd->dev, data, bytes);
+ pthread_mutex_lock(&pawd->mutex);
+ if (ret == 0) { /* failure */
+ ret = -E_AO_PLAY;
+ goto fail;
+ }
btr_consume(btrn, bytes);
}
-unlock:
- pthread_mutex_unlock(&pawd->mutex);
-out:
+fail:
+ btr_remove_node(&pawd->thread_btrn);
assert(ret < 0);
PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
+ pthread_mutex_unlock(&pawd->mutex);
pthread_exit(NULL);
}
goto remove_thread_btrn;
return 0;
}
+ if (!wn->btrn) {
+ if (!pawd->thread_btrn) {
+ pthread_join(pawd->thread, NULL);
+ return -E_AO_EOF;
+ }
+ PARA_INFO_LOG("waiting for play thread to terminate\n");
+ return 0;
+ }
pthread_mutex_lock(&pawd->mutex);
ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
if (ret > 0) {
btr_pushdown(wn->btrn);
- pthread_cond_signal(&pawd->data_available);
+ if (pthread_cond_signal(&pawd->data_available) != 0) {
+ ret = -E_AO_PTHREAD;
+ PARA_ERROR_LOG("pthread_cond_signal() failed\n");
+ goto remove_thread_btrn;
+ }
}
- pthread_mutex_unlock(&pawd->mutex);
- if (ret >= 0)
+ if (ret >= 0) {
+ pthread_mutex_unlock(&pawd->mutex);
goto out;
- pthread_mutex_lock(&pawd->mutex);
+ }
btr_remove_node(&wn->btrn);
- PARA_INFO_LOG("waiting for thread to terminate\n");
pthread_cond_signal(&pawd->data_available);
pthread_mutex_unlock(&pawd->mutex);
- pthread_join(pawd->thread, NULL);
+ return 0;
remove_thread_btrn:
btr_remove_node(&pawd->thread_btrn);
remove_btrn:
dh[num_lines] = NULL;
w->help.detailed_help = (const char **)dh;
ao_write_cmdline_parser_free(&dummy);
- ao_shutdown();
}
struct remove_attribute_action_data {
/** Message buffer. */
struct para_buffer pb;
- /** Numver of attributes removed. */
+ /** Number of attributes removed. */
int num_removed;
/** Bitwise "or" of the removed attributes. */
uint64_t mask_of_removed_atts;
* used for unset attributes.
*
* In practice, not all 64 attributes are defined. In this case, the function
- * only prints \a N + 1 charaters where \a N is the greatest id of a defined
+ * only prints \a N + 1 characters where \a N is the greatest id of a defined
* attribute.
*/
void get_attribute_bitmap(const uint64_t *atts, char *buf)
result->matches = i9e_complete_commands(ci->word, audiod_completers);
}
+static void version_completer(struct i9e_completion_info *ci,
+ struct i9e_completion_result *cr)
+{
+ char *opts[] = {"-v", NULL};
+
+ if (ci->word_num <= 2 && ci->word && ci->word[0] == '-')
+ i9e_complete_option(opts, ci, cr);
+}
+
static void stat_completer(struct i9e_completion_info *ci,
struct i9e_completion_result *cr)
{
N: tasks
D: list current tasks
U: tasks
-H: print the list of task ids together with the status of each task
+H: Print the list of task ids together with the status of each task.
---
N: term
D: terminate audiod
U: term
H: Stop all decoders, shut down connection to para_server and exit.
+---
+N: version
+D: print the version of para_audiod
+U: version [-v]
+H: If the -v option is given, a more detailed version text is printed.
#include "string.h"
#include "write.h"
#include "fd.h"
+#include "version.h"
#include "audiod_command_list.h"
extern struct sched sched;
return 1;
}
+static int com_version(int fd, int argc, char **argv)
+{
+ int ret;
+ char *msg;
+
+ if (argc > 1 && strcmp(argv[1], "-v") == 0)
+ msg = make_message("%s", version_text("audiod"));
+ else
+ msg = make_message("%s\n", version_single_line("audiod"));
+ ret = client_write(fd, msg);
+ free(msg);
+ if (ret >= 0)
+ close(fd);
+ return ret;
+}
+
static int check_perms(uid_t uid)
{
int i;
* For licencing details see COPYING.LIB.
*/
-/**
- * \file bitstream.c Bitstream API.
- */
+/** \file bitstream.c Bitstream API for the wma decoder. */
#include <stdlib.h>
#include <inttypes.h>
const void *bits, const void *codes, int codes_size,
uint32_t code_prefix, int n_prefix)
{
- int i, j, k, n, table_size, table_index, nb, n1, idx, code_prefix2,
- symbol;
+ int i, j, k, n, table_size, table_index, nb, n1, idx;
uint32_t code;
VLC_TYPE(*table)[2];
table = &vlc->table[table_index];
for (i = 0; i < table_size; i++) {
- table[i][1] = 0; //bits
- table[i][0] = -1; //codes
+ table[i][1] = 0; /* bits */
+ table[i][0] = -1; /* codes */
}
- /* map codes and compute auxillary table sizes */
+ /* map codes and compute auxiliary table sizes */
for (i = 0; i < nb_codes; i++) {
GET_DATA(n, bits, i, 1);
- GET_DATA(code, codes, i, codes_size);
/* we accept tables with holes */
+ n -= n_prefix;
if (n <= 0)
continue;
- symbol = i;
+ GET_DATA(code, codes, i, codes_size);
/* if code matches the prefix, it is in the table */
- n -= n_prefix;
- code_prefix2 = code >> n;
- if (n <= 0 || code_prefix2 != code_prefix)
+ if ((code >> n) != code_prefix)
continue;
if (n <= table_nb_bits) {
/* no need to add another table */
j = (code << (table_nb_bits - n)) & (table_size - 1);
nb = 1 << (table_nb_bits - n);
for (k = 0; k < nb; k++) {
- if (table[j][1] /* bits */ != 0) {
- PARA_EMERG_LOG("incorrect code\n");
- exit(EXIT_FAILURE);
- }
- table[j][1] = n; //bits
- table[j][0] = symbol;
+ assert(table[j][1] == 0); /* incorrect code */
+ table[j][1] = n; /* bits */
+ table[j][0] = i;
j++;
}
} else {
n -= table_nb_bits;
j = (code >> n) & ((1 << table_nb_bits) - 1);
/* compute table size */
- n1 = -table[j][1]; //bits
+ n1 = -table[j][1]; /* bits */
if (n > n1)
n1 = n;
- table[j][1] = -n1; //bits
+ table[j][1] = -n1; /* bits */
}
}
- /* fill auxillary tables recursively */
+ /* fill auxiliary tables recursively */
for (i = 0; i < table_size; i++) {
- n = table[i][1]; //bits
+ n = table[i][1]; /* bits */
if (n < 0) {
n = -n;
if (n > table_nb_bits) {
n = table_nb_bits;
- table[i][1] = -n; //bits
+ table[i][1] = -n; /* bits */
}
idx = build_table(vlc, n, nb_codes, bits, codes,
codes_size, (code_prefix << table_nb_bits) | i,
n_prefix + table_nb_bits);
/* vlc->table might have changed */
table = &vlc->table[table_index];
- table[i][0] = idx; //code
+ table[i][0] = idx; /* code */
}
}
return table_index;
* Build VLC decoding tables suitable for use with get_vlc().
*
* \param vlc The structure to be initialized.
- *
- * \param nb_bits Set the decoding table size (2^nb_bits) entries. The bigger
- * it is, the faster is the decoding. But it should not be too big to save
- * memory and L1 cache. '9' is a good compromise.
- *
- * \param nb_codes Number of vlcs codes.
- *
+ * \param nb_bits Set the decoding table size (2^nb_bits) entries.
+ * \param nb_codes Number of vlc codes.
* \param bits Table which gives the size (in bits) of each vlc code.
- *
* \param codes Table which gives the bit pattern of of each vlc code.
- *
* \param codes_size The number of bytes of each entry of the \a codes tables.
*
+ * The bigger \a nb_bits is, the faster is the decoding. But it should not be
+ * too big to save memory and L1 cache. '9' is a good compromise.
+ *
* The wrap and size parameters allow to use any memory configuration and
* types (byte/word/long) to store the bits and codes tables.
*/
* Parse a vlc code.
*
* \param gbc The getbit context structure.
- *
* \param table The vlc tables to use.
- *
- * \param bits The number of bits which will be read at once, must be
- * identical to nb_bits in init_vlc().
- *
- * \param max_depth The number of times bits bits must be read to completely
+ * \param bits The number of bits which will be read at once.
+ * \param max_depth The number of times \a bits bits must be read to completely
* read the longest vlc code = (max_vlc_length + bits - 1) / bits.
*
+ * The \a bits parameter must be identical to the \a nb_bits value supplied to
+ * \ref init_vlc().
+ *
* \return The vlc code.
*/
int get_vlc(struct getbit_context *gbc, VLC_TYPE(*table)[2], int bits,
/**
* Initialize a getbit_context structure.
*
- * \param buffer The bitstream buffer. It must be 4 bytes larger then the
- * actual read bits because the bitstream reader might read 32 bits at once and
- * could read over the end.
+ * \param gbc The structure to initialize.
+ * \param buffer The bitstream buffer.
+ * \param size The size of the buffer in bytes.
*
- * \param bit_size The size of the buffer in bytes.
+ * The bitstream buffer must be 4 bytes larger then the actual read bits
+ * because the bitstream reader might read 32 bits at once and could read over
+ * the end.
*/
static inline void init_get_bits(struct getbit_context *gbc,
const uint8_t *buffer, int size)
void free_vlc(struct vlc *vlc);
int get_vlc(struct getbit_context *gbc, VLC_TYPE(*table)[2], int bits,
int max_depth);
-
switch (state) {
case 0:
- if (target) {
- if (tarindex >= targsize)
- return -E_BASE64;
- target[tarindex] = (pos - Base64) << 2;
- }
+ if (tarindex >= targsize)
+ return -E_BASE64;
+ target[tarindex] = (pos - Base64) << 2;
state = 1;
break;
case 1:
- if (target) {
- if (tarindex + 1 >= targsize)
- return -E_BASE64;
- target[tarindex] |= (pos - Base64) >> 4;
- target[tarindex+1] = ((pos - Base64) & 0x0f)
- << 4 ;
- }
+ if (tarindex + 1 >= targsize)
+ return -E_BASE64;
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex + 1] = ((pos - Base64) & 0x0f) << 4;
tarindex++;
state = 2;
break;
case 2:
- if (target) {
- if (tarindex + 1 >= targsize)
- return -E_BASE64;
- target[tarindex] |= (pos - Base64) >> 2;
- target[tarindex+1] = ((pos - Base64) & 0x03)
- << 6;
- }
+ if (tarindex + 1 >= targsize)
+ return -E_BASE64;
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex + 1] = ((pos - Base64) & 0x03) << 6;
tarindex++;
state = 3;
break;
case 3:
- if (target) {
- if (tarindex >= targsize)
- return -E_BASE64;
- target[tarindex] |= (pos - Base64);
- }
+ if (tarindex >= targsize)
+ return -E_BASE64;
+ target[tarindex] |= pos - Base64;
tarindex++;
state = 0;
break;
* zeros. If we don't check them, they become a
* subliminal channel.
*/
- if (target && target[tarindex] != 0)
+ if (target[tarindex] != 0)
return -E_BASE64;
}
} else {
#define GUI_THEME_ERRORS
#define RINGBUFFER_ERRORS
#define SCORE_ERRORS
-#define RBTREE_ERRORS
#define RECV_ERRORS
#define IPC_ERRORS
#define DCCP_SEND_ERRORS
PARA_ERROR(AO_PLAY, "ao_play() failed"), \
PARA_ERROR(AO_BAD_SAMPLE_FORMAT, "ao: unsigned sample formats not supported"), \
PARA_ERROR(AO_PTHREAD, "pthread error"), \
+ PARA_ERROR(AO_EOF, "ao: end of file"), \
#define COMPRESS_FILTER_ERRORS \
test_options += --trash-dir $(trash_dir)
test_options += --executables "$(prefixed_executables)"
test_options += --objects "$(basename $(all_objs))"
+test_options += --man-dir $(man_dir)
ifdef V
ifeq ("$(origin V)", "command line")
--- /dev/null
+#!/usr/bin/env bash
+
+test_description='Parse generated man pages.
+
+Simple sanity checks of some man pages.
+
+* para_audiod: Check that list of audiod commands is present
+* para_server: Check that list of server/afs commands is present
+* para_play: Check that list of play commands is present
+
+* para_{recv,filter,write,audiod}: Check for presence of
+filter/receiver/writer options as appropriate '
+
+. ${0%/*}/test-lib.sh
+
+rfw_regex='Options for .\{100,\}Options for ' # recv/filter/writer
+
+grep_man()
+{
+ local regex="$1" exe="$2"
+ tr '\n' ' ' < "$o_man_dir/para_$exe.1" | grep -q "$regex"
+}
+
+# check that options of all reveivers/filters/writers are contained
+# in the man pages
+
+regex="$rfw_regex"
+test_expect_success 'para_recv: receiver options' "grep_man '$regex' recv"
+test_expect_success 'para_filter: filter options' "grep_man '$regex' filter"
+test_expect_success 'para_write: writer options' "grep_man '$regex' write"
+test_require_objects "audiod"
+if [[ -n "$result" ]]; then
+ test_skip 'para_audiod' "missing object(s): $result"
+else
+ test_expect_success 'para_audiod: recv/filter/writer options' \
+ "grep_man '$regex' audiod"
+fi
+
+# check various command lists
+
+test_require_objects "audiod"
+if [[ -n "$result" ]]; then
+ test_skip 'para_audiod' "missing object(s): $result"
+else
+ regex='LIST OF AUDIOD COMMANDS.\{200,\}'
+ test_expect_success 'para_audiod: command list' \
+ "grep_man '$regex' audiod"
+fi
+
+test_require_objects "server"
+missing_objects="$result"
+if [[ -n "$missing_objects" ]]; then
+ test_skip "para_server" "missing object(s): $missing_objects"
+else
+ regex='LIST OF SERVER COMMANDS.\{100,\}LIST OF AFS COMMANDS'
+ test_expect_success 'para_server: server/afs commands' \
+ "grep_man '$regex' server"
+fi
+
+# para_play is always built
+regex='LIST OF COMMANDS.\{100,\}'
+test_expect_success 'para_play: play commands' "grep_man '$regex' play"
+regex="$rfw_regex"
+test_done
if [[ "$o_nocolor" != "true" && -n "$1" ]]; then
export TERM=$ORIGINAL_TERM
case "$1" in
- error) tput bold; tput setaf 1;;
- skip) tput setaf 5;;
+ error) tput $C_BOLD; tput $C_SETAF 1;;
+ skip) tput $C_SETAF 5;;
ok)
(($o_verbose == 0)) && return
- tput setaf 2;;
- pass) tput bold; tput setaf 2;;
- info) tput setaf 3;;
+ tput $C_SETAF 2;;
+ pass) tput $C_BOLD; tput $C_SETAF 2;;
+ info) tput $C_SETAF 3;;
run)
(($o_verbose == 0)) && return
- tput setaf 6;;
+ tput $C_SETAF 6;;
esac
fi
shift
printf "%s\n" "$*"
if [[ "$o_nocolor" != "true" && -n "$1" ]]; then
- tput sgr0
+ tput $C_SGR0
export TERM=dumb
fi
}
result="false"
[[ "$TERM" == "dumb" ]] && return
[[ -t 1 ]] || return
- tput bold >/dev/null 2>&1 || return
- tput setaf 1 >/dev/null 2>&1 || return
- tput sgr0 >/dev/null 2>&1 || return
+ C_BOLD='bold'
+ tput $C_BOLD &>/dev/null || {
+ C_BOLD='md'
+ tput $C_BOLD &>/dev/null
+ } || return
+ C_SETAF='setaf'
+ tput $C_SETAF 1 &>/dev/null || {
+ C_SETAF='AF'
+ tput $C_SETAF 1 &>/dev/null
+ } || return
+ C_SGR0='sgr0'
+ tput $C_SGR0 >/dev/null 2>&1 || {
+ C_SGR0='me'
+ tput $C_SGR0 &>/dev/null
+ } || return
result="true"
}
-v=1|--verbose=1) o_verbose="1"; shift;;
-v|--verbose|-v=2|--verbose=2) o_verbose="2"; shift;;
--no-color) o_nocolor="true"; shift;;
+ --man-dir) export o_man_dir="$2"; shift; shift;;
--results-dir) o_results_dir="$2"; shift; shift;;
--trash-dir) o_trash_dir="$2"; shift; shift;;
--executables-dir) export o_executables_dir="$2"; shift; shift;;
[[ -z "$o_results_dir" ]] && o_results_dir="$test_dir/test-results"
[[ -z "$o_executables_dir" ]] && o_executables_dir="$test_dir/.."
[[ -z "$o_trash_dir" ]] && o_trash_dir="$test_dir/trashes"
+ [[ -z "$o_man_dir" ]] && o_man_dir="$test_dir/../build/man/man1"
# we want alsolute paths because relative paths become invalid
# after changing to the trash dir
[[ -n "${o_results_dir##/*}" ]] && o_results_dir="$wd/$o_results_dir"
[[ -n "${o_executables_dir##/*}" ]] && o_executables_dir="$wd/$o_results_dir"
+ [[ -n "${o_man_dir##/*}" ]] && o_man_dir="$wd/$o_man_dir"
[[ -n "${o_trash_dir##/*}" ]] && o_trash_dir="$wd/$o_trash_dir"
mkdir -p "$o_results_dir"
The audio format handler code is linked into para_server and executed
via the _add_ command. The same code is also available as a stand-alone
-tool, para_afh, which can be used to print the technical data, the
-chunk table and the meta data of a file.
+tool, para_afh, which prints the technical data, the chunk table
+and the meta data of a file. Moreover, all audio format handlers are
+combined in the afh receiver which is part of para_recv and para_play.
----------
Networking
uint32_t bit_rate;
/** Further decoding information (ignored). */
uint32_t flags1;
- /** Whether to use exp_vlc, bit reservoir, variable block len. */
+ /** Encodes exp_vlc, bit reservoir, vbl, number of block sizes. */
uint16_t flags2;
+ /** Whether exponents are coded with VLC codes. */
+ bool use_exp_vlc;
+ /** If false, a frame is equal to a superframe. */
+ bool use_bit_reservoir;
+ /** Whether blocks are of variable or of constant size. */
+ bool use_variable_block_len;
};
/* wma_common.c */
afhi->frequency = ahi.sample_rate;
afhi->channels = ahi.channels;
afhi->header_len = ahi.header_len;
+
+ afhi->techinfo = make_message("%s%s%s%s%s",
+ ahi.use_exp_vlc? "exp vlc" : "",
+ (ahi.use_bit_reservoir && ahi.use_exp_vlc)? ", " : "",
+ ahi.use_bit_reservoir? "bit reservoir" : "",
+ (ahi.use_variable_block_len &&
+ (ahi.use_exp_vlc || ahi.use_bit_reservoir)? ", " : ""),
+ ahi.use_variable_block_len? "vbl" : ""
+ );
wma_make_chunk_table(map + ahi.header_len, numbytes - ahi.header_len,
ahi.block_align, afhi);
read_asf_tags(map, ahi.header_len, &afhi->tags);
ahi->flags2 = read_u16(start + 60);
PARA_INFO_LOG("read_asf_header: flags1: %d, flag2: %d\n",
ahi->flags1, ahi->flags2);
+ ahi->use_exp_vlc = ahi->flags2 & 0x0001;
+ ahi->use_bit_reservoir = ahi->flags2 & 0x0002;
+ ahi->use_variable_block_len = ahi->flags2 & 0x0004;
return 1;
}
/** Information contained in the audio file header. */
struct asf_header_info ahi;
struct getbit_context gb;
- /** Whether to use the bit reservoir. */
- int use_bit_reservoir;
- /** Whether to use variable block length. */
- int use_variable_block_len;
- /** Whether to use exponent coding. */
- int use_exp_vlc;
/** Whether perceptual noise is added. */
int use_noise_coding;
/** Depends on number of the bits per second and the frame length. */
int byte_offset_bits;
- /** Only used if use_exp_vlc is true. */
+ /** Only used if ahi->use_exp_vlc is true. */
struct vlc exp_vlc;
uint16_t exponent_bands[BLOCK_NB_SIZES][25];
/** The index of the first coef in high band. */
int frame_len;
/** log2 of frame_len. */
int frame_len_bits;
- /** Number of block sizes. */
+ /** Number of block sizes, one if !ahi->use_variable_block_len. */
int nb_block_sizes;
/* block info */
int reset_block_lengths;
for (i = 0; i < pwd->nb_block_sizes; i++)
imdct_end(pwd->mdct_ctx[i]);
- if (pwd->use_exp_vlc)
+ if (pwd->ahi.use_exp_vlc)
free_vlc(&pwd->exp_vlc);
if (pwd->use_noise_coding)
free_vlc(&pwd->hgain_vlc);
else
pwd->frame_len_bits = 11;
pwd->frame_len = 1 << pwd->frame_len_bits;
- if (pwd->use_variable_block_len) {
+ if (pwd->ahi.use_variable_block_len) {
int nb_max, nb;
nb = ((flags2 >> 3) & 3) + 1;
if ((ahi->bit_rate / ahi->channels) >= 32000)
pwd->frame_len, bps, bps1,
high_freq, pwd->byte_offset_bits);
PARA_INFO_LOG("use_noise_coding=%d use_exp_vlc=%d nb_block_sizes=%d\n",
- pwd->use_noise_coding, pwd->use_exp_vlc, pwd->nb_block_sizes);
+ pwd->use_noise_coding, pwd->ahi.use_exp_vlc, pwd->nb_block_sizes);
compute_scale_factor_band_sizes(pwd, high_freq);
/* init MDCT windows : simple sinus window */
if (pwd->use_noise_coding) {
/* init the noise generator */
- if (pwd->use_exp_vlc)
+ if (pwd->ahi.use_exp_vlc)
pwd->noise_mult = 0.02;
else
pwd->noise_mult = 0.04;
return ret;
}
- pwd->use_exp_vlc = pwd->ahi.flags2 & 0x0001;
- pwd->use_bit_reservoir = pwd->ahi.flags2 & 0x0002;
- pwd->use_variable_block_len = pwd->ahi.flags2 & 0x0004;
-
ret = wma_init(pwd);
if (ret < 0)
return ret;
wma_hgain_huffcodes, 2);
}
- if (pwd->use_exp_vlc) {
+ if (pwd->ahi.use_exp_vlc) {
PARA_INFO_LOG("using exp_vlc\n");
init_vlc(&pwd->exp_vlc, EXPVLCBITS, sizeof(wma_scale_huffbits),
wma_scale_huffbits, wma_scale_huffcodes, 4);
int nb_coefs[MAX_CHANNELS];
/* compute current block length */
- if (pwd->use_variable_block_len) {
+ if (pwd->ahi.use_variable_block_len) {
n = wma_log2(pwd->nb_block_sizes - 1) + 1;
if (pwd->reset_block_lengths) {
if ((pwd->block_len_bits == pwd->frame_len_bits) || get_bit(&pwd->gb)) {
for (ch = 0; ch < pwd->ahi.channels; ch++) {
if (pwd->channel_coded[ch]) {
- if (pwd->use_exp_vlc) {
+ if (pwd->ahi.use_exp_vlc) {
ret = decode_exp_vlc(pwd, ch);
if (ret < 0)
return ret;
buf_size = pwd->ahi.block_align;
samples = data;
init_get_bits(&pwd->gb, buf, buf_size);
- if (pwd->use_bit_reservoir) {
+ if (pwd->ahi.use_bit_reservoir) {
int i, nb_frames, bit_offset, pos, len;
uint8_t *q;