Skip to content

Commit

Permalink
1.4beta1 - merge output branch
Browse files Browse the repository at this point in the history
- native support of dsd playback to dop capable dac or via conversion to pcm and resampling
- support dop in flac playback to dop dacs
- support of output to stdout
- support of resampling only when sample rate is not natively supported
- fix problem with libmpg123 playback not playing to end of track
- add ablity for player name change to be stored locally in a file (to emulate hardware where name is stored on player)
  • Loading branch information
triode committed Dec 22, 2013
1 parent fcfe774 commit 11c3a1f
Show file tree
Hide file tree
Showing 26 changed files with 3,408 additions and 1,612 deletions.
57 changes: 57 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Version 1.0 - 15/2/13
=====================
- initial release

Version 1.1 - 12/4/13
=====================

Minor changes
- add timeout on slimproto connection to detect dead server
- fix issue with clipping on windows by disabling portaudio dither
- silence alsa error messages on linux alsa builds unless debugging is enabled
- hide some additional error messages unless debuging is enabled so usb dacs produce less error messages when turned off and on

Version 1.2 - 6/7/13
====================

Features
- support of upsampling via libsoxr

Minor changes
- command line option for setting the service address now requires "-s" before the server address
- fixes a bug where the channels could become swapped when using S16_LE ALSA output
- falls back to polling for a new server if one is not found for more than 30 seconds
- fixes play of wav/aiff local files when the LocalPlayer plugin is active

Version 1.3 - 6/10/13
=====================

Features
- support for wma/alac decode via ffmpeg library (requires compilation with -DFFMPEG)
- support for export of audio data to jivelite to enable visulizations on linux (requires compilation with -DVISEXPORT)

Minor changes
- support async as well as sync resampling rates
- support on/off of audio device with portaudio
- improved gapless support for aac/mad when skipping to mid track (based on patches from Wouter Ellenbroek)
- various bug fixes

Version 1.3.1 - 25/11/13
========================

Minor changes
- support of compile time linking for distro packaging, uses -DLINKALL option

Version 1.4 (beta)
==================

Features
- native support of dsd playback to dop capable dac or via conversion to pcm and resampling
- support dop in flac playback to dop dacs
- support of output to stdout

Minor changes
- support of resampling only when sample rate is not natively supported
- fix problem with libmpg123 playback not playing to end of track
- add ablity for player name change to be stored locally in a file (to emulate hardware where name is stored on player)

61 changes: 49 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,60 @@ CFLAGS ?= -Wall -fPIC -O2 $(OPTS)
LDFLAGS ?= -lasound -lpthread -lm -lrt
EXECUTABLE ?= squeezelite

SOURCES = main.c slimproto.c utils.c output.c buffer.c stream.c decode.c process.c resample.c flac.c pcm.c mad.c vorbis.c faad.c mpg.c ffmpeg.c
DEPS = squeezelite.h slimproto.h
# passing one or more of these in $(OPTS) enables optional feature inclusion
OPT_DSD = -DDSD
OPT_FF = -DFFMPEG
OPT_LINKALL = -DLINKALL
OPT_RESAMPLE= -DRESAMPLE
OPT_VIS = -DVISEXPORT

UNAME = $(shell uname -s)
SOURCES = \
main.c slimproto.c buffer.c stream.c utils.c \
output.c output_alsa.c output_pa.c output_stdout.c output_pack.c decode.c \
flac.c pcm.c mad.c vorbis.c faad.c mpg.c

ifneq (,$(findstring -DLINKALL, $(CFLAGS)))
LDFLAGS += -lFLAC -lmad -lvorbisfile -lfaad -lmpg123
ifneq (,$(findstring -DFFMPEG, $(CFLAGS)))
LDFLAGS += -lavcodec -lavformat -lavutil
SOURCES_DSD = dsd.c dop.c dsd2pcm/dsd2pcm.c
SOURCES_FF = ffmpeg.c
SOURCES_RESAMPLE = process.c resample.c
SOURCES_VIS = output_vis.c

LINK_LINUX = -ldl

LINKALL = -lFLAC -lmad -lvorbisfile -lfaad -lmpg123
LINKALL_FF = -lavcodec -lavformat -lavutil
LINKALL_RESAMPLE = -lsoxr

DEPS = squeezelite.h slimproto.h

UNAME = $(shell uname -s)

# add optional sources
ifneq (,$(findstring $(OPT_DSD), $(CFLAGS)))
SOURCES += $(SOURCES_DSD)
endif
ifneq (,$(findstring $(OPT_FF), $(CFLAGS)))
SOURCES += $(SOURCES_FF)
endif
ifneq (,$(findstring $(OPT_RESAMPLE), $(CFLAGS)))
SOURCES += $(SOURCES_RESAMPLE)
endif
ifneq (,$(findstring $(OPT_VIS), $(CFLAGS)))
SOURCES += $(SOURCES_VIS)
endif

# add optional link options
ifneq (,$(findstring $(OPT_LINKALL), $(CFLAGS)))
LDFLAGS += $(LINKALL)
ifneq (,$(findstring $(OPT_FF), $(CFLAGS)))
LDFLAGS += $(LINKALL_FF)
endif
ifneq (,$(findstring -DRESAMPLE, $(CFLAGS)))
LDFLAGS += -lsoxr
ifneq (,$(findstring $(OPT_RESAMPLE), $(CFLAGS)))
LDFLAGS += $(LINKALL_RESAMPLE)
endif
else
# if not LINKALL and linux add -ldl
# if not LINKALL and linux add LINK_LINUX
ifeq ($(UNAME), Linux)
LDFLAGS += -ldl
LDFLAGS += $(LINK_LINUX)
endif
endif

Expand All @@ -33,7 +70,7 @@ $(EXECUTABLE): $(OBJECTS)
$(OBJECTS): $(DEPS)

.c.o:
$(CC) $(CFLAGS) $< -c -o $@
$(CC) $(CFLAGS) $(CPPFLAGS) $< -c -o $@

clean:
rm -f $(OBJECTS) $(EXECUTABLE)
9 changes: 6 additions & 3 deletions decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,11 @@ void decode_init(log_level level, const char *opt) {
LOG_INFO("init decode");

// register codecs
// alc,wma,wmap,wmal,aac,spt,ogg,ogf,flc,aif,pcm,mp3
// dsf,dff,alc,wma,wmap,wmal,aac,spt,ogg,ogf,flc,aif,pcm,mp3
i = 0;
#if DSD
if (!opt || strstr(opt, "dsd")) codecs[i++] = register_dsd();
#endif
#if FFMPEG
if (!opt || strstr(opt, "alac")) codecs[i++] = register_ff("alc");
if (!opt || strstr(opt, "wma")) codecs[i++] = register_ff("wma");
Expand Down Expand Up @@ -191,11 +194,11 @@ void decode_flush(void) {
UNLOCK_D;
}

unsigned decode_newstream(unsigned sample_rate, unsigned max_sample_rate) {
unsigned decode_newstream(unsigned sample_rate, unsigned supported_rates[]) {

MAY_PROCESS(
if (decode.process) {
return process_newstream(&decode.direct, sample_rate, max_sample_rate);
return process_newstream(&decode.direct, sample_rate, supported_rates);
}
);

Expand Down
90 changes: 90 additions & 0 deletions dop.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Squeezelite - lightweight headless squeezebox emulator
*
* (c) Adrian Smith 2012, 2013, triode1@btinternet.com
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/

// DSP over PCM (DOP) specific functions

#include "squeezelite.h"

#if DSD

extern struct buffer *outputbuf;
extern struct outputstate output;

#define LOCK_O mutex_lock(outputbuf->mutex)
#define UNLOCK_O mutex_unlock(outputbuf->mutex)

// check for 32 dop marker frames to see if this is dop in flac
// dop is always encoded in 24 bit samples with marker 0x0005xxxx or 0x00FAxxxx
bool is_flac_dop(u32_t *lptr, u32_t *rptr, frames_t frames) {
int matched = 0;
u32_t next = 0;

while (frames--) {
if (((*lptr & 0x00FF0000) == 0x00050000 && (*rptr & 0x00FF0000) == 0x00050000) ||
((*lptr & 0x00FF0000) == 0x00FA0000 && (*rptr & 0x00FF0000) == 0x00FA0000)) {
if (*lptr >> 24 == next) {
matched++;
next = ( 0x05 + 0xFA ) - next;
} else {
next = *lptr >> 24;
matched = 1;
}
} else {
return false;
}
if (matched == 32) {
return true;
}

++lptr; ++rptr;
}
return false;
}

// update the dop marker for frames in the output buffer
// performaned on all output including silence to maintain marker phase consitency
void update_dop_marker(u32_t *ptr, frames_t frames) {
static u32_t marker = 0x05;
while (frames--) {
u32_t scaled_marker = marker << 24;
*ptr = (*ptr & 0x00FFFFFF) | scaled_marker;
++ptr;
*ptr = (*ptr & 0x00FFFFFF) | scaled_marker;
++ptr;
marker = ( 0x05 + 0xFA ) - marker;
}
}

// fill silence buffer with 10101100 which represents dop silence
// leave marker zero it will be updated at output, leave lsb zero
void dop_silence_frames(u32_t *ptr, frames_t frames) {
while (frames--) {
*ptr++ = 0x00ACAC00;
*ptr++ = 0x00ACAC00;
}
}

void dop_init(bool enable) {
LOCK_O;
output.has_dop = enable;
UNLOCK_O;
}

#endif // DSD
Loading

0 comments on commit 11c3a1f

Please sign in to comment.