Skip to content

Commit 0bc33e7

Browse files
committed
v0.7.9
1 parent e06b279 commit 0bc33e7

File tree

7 files changed

+258
-200
lines changed

7 files changed

+258
-200
lines changed

src/cmdline.cpp

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ void CmdLine::PrintWav(const AudioFile &myWav)
3131
void CmdLine::PrintMode()
3232
{
3333
std::cout << " Profile: ";
34+
std::cout << "mt" << opt.mt_mode;
3435
std::cout << " " << opt.max_framelen << "s";
35-
if (opt.zero_mean) std::cout << " zero-mean";
36-
if (opt.sparse_pcm) std::cout << " sparse-pcm";
3736
if (opt.optimize) {
3837
std::cout << " opt (" << std::format("{:.1f}%", opt.optimize_fraction*100.0);
3938
std::cout << ",n=" << opt.optimize_maxnfunc << ",";
@@ -47,8 +46,11 @@ void CmdLine::PrintMode()
4746
case opt.SearchCost::Bitplane:cost_str="bpn";break;
4847
default:break;
4948
}
50-
std::cout << cost_str << ")\n";
49+
std::cout << cost_str << ")";
5150
}
51+
if (opt.zero_mean) std::cout << " zero-mean";
52+
if (opt.sparse_pcm) std::cout << " sparse-pcm";
53+
std::cout << '\n';
5254
std::cout << std::endl;
5355
}
5456

@@ -65,6 +67,20 @@ void CmdLine::Split(const std::string &str,std::string &key,std::string &val,con
6567
}
6668
}
6769

70+
double CmdLine::stod_safe(const std::string& str)
71+
{
72+
double d;
73+
try {
74+
d = std::stod(str);
75+
} catch (const std::invalid_argument&) {
76+
std::cerr << "stod: argument is invalid\n";
77+
throw;
78+
} catch (const std::out_of_range&) {
79+
std::cerr << "stod: argument is out of range for a double\n";
80+
throw;
81+
}
82+
return d;
83+
}
6884

6985
int CmdLine::Parse(int argc,char *argv[])
7086
{
@@ -89,7 +105,7 @@ int CmdLine::Parse(int argc,char *argv[])
89105
else if (key=="--LIST") mode=LIST;
90106
else if (key=="--LISTFULL") mode=LISTFULL;
91107
else if (key=="--VERBOSE") {
92-
if (val.length()) opt.verbose_level=stoi(val);
108+
if (val.length()) opt.verbose_level=std::max(0,stoi(val));
93109
else opt.verbose_level=1;
94110
}
95111
else if (key=="--NORMAL") {
@@ -116,7 +132,7 @@ int CmdLine::Parse(int argc,char *argv[])
116132
std::vector<std::string>vs;
117133
StrUtils::SplitToken(val,vs,",");
118134
if (vs.size()>=2) {
119-
opt.optimize_fraction=std::clamp(std::stod(vs[0]),0.,1.);
135+
opt.optimize_fraction=std::clamp(stod_safe(vs[0]),0.,1.);
120136
opt.optimize_maxnfunc=std::clamp(std::stoi(vs[1]),0,10000);
121137
if (vs.size()>=3) {
122138
std::string cf=StrUtils::str_up(vs[2]);
@@ -133,7 +149,10 @@ int CmdLine::Parse(int argc,char *argv[])
133149
}
134150
}
135151
else if (key=="--FRAMELEN") {
136-
if (val.length()) opt.max_framelen=stoi(val);
152+
if (val.length()) opt.max_framelen=std::max(0,stoi(val));
153+
}
154+
else if (key=="--MT-MODE") {
155+
if (val.length()) opt.mt_mode=std::max(0,stoi(val));
137156
}
138157
else if (key=="--SPARSE-PCM") {
139158
if (val=="NO" || val=="0") opt.sparse_pcm=0;
@@ -179,11 +198,11 @@ int CmdLine::Process()
179198
if (mySac.OpenWrite(soutputfile)==0) {
180199
std::cout << "ok\n";
181200
PrintMode();
182-
Codec myCodec;
201+
Codec myCodec(opt);
183202

184203
Timer time;
185204
time.start();
186-
myCodec.EncodeFile(myWav,mySac,opt);
205+
myCodec.EncodeFile(myWav,mySac);
187206
time.stop();
188207

189208
uint64_t infilesize=myWav.getFileSize();
@@ -219,9 +238,10 @@ int CmdLine::Process()
219238
mySac.setKBPS(kbps);
220239
PrintWav(mySac);
221240
std::cout << " Profile: ";
241+
std::cout << "mt" << opt.mt_mode;
222242
std::cout << " " << static_cast<int>(mySac.mcfg.max_framelen) << "s";
223243
std::cout << std::endl;
224-
std::cout << " Ratio: " << std::fixed << std::setprecision(3) << bps << " bits per sample\n\n";
244+
std::cout << " Ratio: " << std::fixed << std::setprecision(3) << bps << " bps\n\n";
225245
std::cout << " Audio MD5: ";
226246
for (auto x : md5digest) std::cout << std::hex << (int)x;
227247
std::cout << std::dec << '\n';
@@ -236,12 +256,22 @@ int CmdLine::Process()
236256
std::cout << "Create: '" << soutputfile << "': ";
237257
if (myWav.OpenWrite(soutputfile)==0) {
238258
std::cout << "ok\n";
239-
Codec myCodec;
259+
260+
Timer time;
261+
time.start();
262+
263+
Codec myCodec(opt);
240264
myCodec.DecodeFile(mySac,myWav);
241265
MD5::Finalize(&myWav.md5ctx);
242-
bool md5diff=std::memcmp(myWav.md5ctx.digest, md5digest, 16);
243-
std::cout << '\n';
266+
time.stop();
267+
268+
double xrate=0.0;
269+
if (time.elapsedS() > 0.0)
270+
xrate=(myWav.getNumSamples()/double(myWav.getSampleRate()))/time.elapsedS();
271+
std::cout << "\n Speed " << std::format("{:.3f}x",xrate) << '\n';
272+
244273
std::cout << " Audio MD5: ";
274+
bool md5diff=std::memcmp(myWav.md5ctx.digest, md5digest, 16);
245275
if (!md5diff) std::cout << "ok\n";
246276
else {
247277
std::cout << "Error (";

src/cmdline.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,18 @@ const char SACHelp[] =
1212
" --high high compression, slow\n"
1313
" --veryhigh very high compression, really slow\n"
1414
" --best you asked for it\n"
15+
" --insane :>\n"
1516
" --decode decode input.sac to output.wav\n"
1617
" --list list info about input.sac\n"
17-
" --listfull verbose info about input\n\n"
18+
" --listfull verbose info about input\n"
19+
" --verbose=n verbosity level (def=0)\n\n"
1820
" supported types: 1-16 bit, mono/stereo pcm\n"
19-
" advanced options (automatically set per profile)\n"
21+
" advanced options (automatically set)\n"
2022
" --reset-opt reset opt params at frame boundaries\n"
2123
" --optimize=# frame-based optimization\n"
2224
" no|s,n(,c) s=[0,1.0],n=[0,10000]\n"
2325
" c=[l1,rms,glb,ent,bpn]\n"
26+
" --mt-mode=n multi-threading level n=[0-2]\n"
2427
" --zero-mean zero-mean input\n"
2528
" --framelen=n def=8 (seconds)\n"
2629
" --sparse-pcm enable pcm modelling\n";
@@ -32,6 +35,7 @@ class CmdLine {
3235
int Parse(int argc,char *argv[]);
3336
int Process();
3437
private:
38+
double stod_safe(const std::string& str);
3539
void PrintMode();
3640
void PrintWav(const AudioFile &myWav);
3741
void Split(const std::string &str,std::string &key,std::string &val,const char splitval='=');

src/libsac/cost.h

Lines changed: 47 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,37 @@
55
#include "../common/utils.h"
66
#include <cmath>
77

8+
typedef std::span<int32_t> span_i32;
9+
810
class CostFunction {
911
public:
10-
CostFunction(){};
11-
virtual double Calc(const int32_t *buf,int numsamples)=0;
12+
CostFunction() {};
13+
virtual double Calc(const span_i32 &buf) const =0;
1214
virtual ~CostFunction(){};
1315
};
1416

1517
class CostL1 : public CostFunction {
1618
public:
17-
double Calc(const int32_t *buf,int numsamples)
19+
double Calc(const span_i32 &buf) const
1820
{
19-
if (numsamples) {
21+
if (buf.size()) {
2022
int64_t sum=0;
21-
for (int i=0;i<numsamples;i++) sum+=std::fabs(buf[i]);
22-
return sum/static_cast<double>(numsamples);
23+
for (const auto val:buf)
24+
sum+=std::fabs(val);
25+
return sum/static_cast<double>(buf.size());
2326
} else return 0.;
2427
}
2528
};
2629

2730
class CostRMS : public CostFunction {
2831
public:
29-
double Calc(const int32_t *buf,int numsamples)
32+
double Calc(const span_i32 &buf) const
3033
{
31-
if (numsamples) {
34+
if (buf.size()) {
3235
int64_t sum=0.0;
33-
for (int i=0;i<numsamples;i++) sum+=buf[i]*buf[i];
34-
return sqrt(sum/static_cast<double>(numsamples));
36+
for (const auto val:buf)
37+
sum+=val*val;
38+
return sqrt(sum/static_cast<double>(buf.size()));
3539
} else return 0.;
3640
}
3741
};
@@ -43,86 +47,52 @@ class CostGolomb : public CostFunction {
4347
const double alpha=0.97;
4448
const double log2=log(2.0);
4549
public:
46-
CostGolomb()
47-
:rm(alpha) {};
48-
double Calc(const int32_t *buf,int numsamples)
50+
CostGolomb(){};
51+
double Calc(const span_i32 &buf) const
4952
{
53+
RunWeight rm(alpha);
5054
int64_t nbits=0;
51-
if (numsamples) {
52-
for (int i=0;i<numsamples;i++) {
53-
int32_t val=MathUtils::S2U(buf[i]);
54-
int m=std::max(static_cast<int>(rm.sum),1);
55-
56-
int q=val/m;
55+
if (buf.size()) {
56+
for (const auto sval:buf) {
57+
const auto m=std::max(static_cast<int32_t>(rm.sum),1);
58+
const auto uval=MathUtils::S2U(sval);
59+
int q=uval/m;
5760
//int r=val-q*m;
5861
nbits+=(q+1);
59-
if (m>1) {
60-
int b=std::ceil(log(m)/log2);
61-
nbits+=b;
62-
};
63-
rm.Update(val);
62+
if (m>1) nbits+=std::ceil(log(m)/log2);
63+
rm.Update(uval);
6464
}
65-
return nbits/static_cast<double>(8*numsamples);
65+
return nbits/static_cast<double>(8*buf.size());
6666
} else return 0;
6767
}
68-
private:
69-
RunWeight rm;
7068
};
7169

7270
// entropy using order-0 markov model
73-
class CostEntropyO0 : public CostFunction {
71+
class CostEntropy : public CostFunction {
7472
public:
75-
CostEntropyO0(){};
76-
double Calc(const int32_t *buf,int numsamples)
73+
CostEntropy(){};
74+
double Calc(const span_i32 &buf) const
7775
{
78-
if (numsamples<=0) return 0.0;
79-
std::vector <int>counts;
80-
std::vector<int32_t> e(numsamples);
81-
int imax=0;
82-
for (int i=0;i<numsamples;i++) {
83-
e[i]=MathUtils::S2U(buf[i]);
84-
if (e[i]>imax) imax=e[i];
85-
}
86-
counts.resize(imax+1);
87-
for (int i=0;i<numsamples;i++) {
88-
counts[e[i]]++;
89-
}
9076
double entropy=0.0;
91-
for (int i=0;i<numsamples;i++) {
92-
double p=counts[e[i]]/double(numsamples);
93-
94-
entropy+=p*log(p);
95-
}
96-
return entropy;
97-
}
98-
};
99-
100-
// entropy using order-0 markov model
101-
class CostEntropyO0b : public CostFunction {
102-
public:
103-
CostEntropyO0b(){};
104-
double Calc(const int32_t *buf,int numsamples)
105-
{
106-
if (numsamples<=0) return 0.0;
107-
int32_t minval = std::numeric_limits<int32_t>::max();
108-
int32_t maxval = std::numeric_limits<int32_t>::min();
109-
for (int i=0;i<numsamples;i++) {
110-
const int32_t val=buf[i];
111-
if (val>maxval) maxval=val;
112-
if (val<minval) minval=val;
113-
}
114-
std::vector<int> counts(maxval-minval+1);
77+
if (buf.size())
78+
{
79+
int32_t minval = std::numeric_limits<int32_t>::max();
80+
int32_t maxval = std::numeric_limits<int32_t>::min();
81+
for (const auto val:buf) {
82+
if (val>maxval) maxval=val;
83+
if (val<minval) minval=val;
84+
}
85+
auto vmap=[&](int32_t val) {return val-minval;};
11586

116-
for (int i=0;i<numsamples;i++) {
117-
int32_t idx=buf[i]-minval;
118-
counts[idx]++;
119-
}
120-
double entropy=0.0;
121-
for (int i=0;i<numsamples;i++) {
122-
int32_t idx=buf[i]-minval;
123-
double p=counts[idx]/double(numsamples);
87+
std::vector<int> counts(maxval-minval+1);
88+
for (const auto val:buf)
89+
counts[vmap(val)]++;
12490

125-
entropy+=p*log(p);
91+
const double invs=1.0/static_cast<double>(buf.size());
92+
for (const auto val:buf) {
93+
const double p=counts[vmap(val)]*invs;
94+
entropy+=p*log(p);
95+
}
12696
}
12797
return entropy;
12898
}
@@ -133,8 +103,9 @@ class CostBitplane : public CostFunction {
133103
public:
134104
CostBitplane() {
135105
}
136-
double Calc(const int32_t *buf,int numsamples)
106+
double Calc(const span_i32 &buf) const
137107
{
108+
int numsamples=buf.size();
138109
std::vector<int32_t> ubuf(numsamples);
139110
int vmax=0;
140111
for (int i=0;i<numsamples;i++) {

0 commit comments

Comments
 (0)