Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements and sf3 import #31

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ if (MINGW)
target_link_libraries(sf3convert
${QT_LIBRARIES}
vorbis
##vorbisfile
vorbisenc
vorbisfile
ogg
sndfile-1
)
Expand All @@ -52,6 +53,8 @@ if (MINGW)
${CROSS}/lib/libsndfile-1.dll
${CROSS}/lib/libogg.dll
${CROSS}/lib/libvorbis.dll
${CROSS}/lib/libvorbisenc.dll
${CROSS}/lib/libvorbisfile.dll
${CROSSQT}/bin/Qt5Core.dll
${CROSSQT}/bin/Qt5Xml.dll
${CROSSQT}/bin/icuin51.dll
Expand Down Expand Up @@ -82,6 +85,28 @@ else (MINGW)
message("libvorbis not found\n")
endif (VORBIS_INCDIR)

##
## libvorbisenc
##

PKGCONFIG1 (vorbisenc 1.3.3 VORBISENC_INCDIR VORBISENC_LIBDIR VORBISENC_LIB VORBISENC_CPP)
if (VORBISENC_INCDIR)
message("libvorbisenc detected ${VORBISENC_INCDIR} ${VORBISENC_LIBDIR} ${VORBISENC_LIB}")
else (VORBISENC_INCDIR)
message("libvorbisenc not found\n")
endif (VORBISENC_INCDIR)

##
## libvorbisfile
##

PKGCONFIG1 (vorbisfile 1.3.3 VORBISFILE_INCDIR VORBISFILE_LIBDIR VORBISFILE_LIB VORBISFILE_CPP)
if (VORBISFILE_INCDIR)
message("libvorbisfile detected ${VORBISFILE_INCDIR} ${VORBISFILE_LIBDIR} ${VORBISFILE_LIB}")
else (VORBISFILE_INCDIR)
message("libvorbisfile not found\n")
endif (VORBISFILE_INCDIR)


##
## libogg
Expand All @@ -103,13 +128,16 @@ else (MINGW)
${SNDFILE_INCDIR}
${OGG_INCDIR}
${VORBIS_INCDIR}
${VORBISENC_INCDIR}
${VORBISFILE_INCDIR}
)

target_link_libraries(sf3convert
${QT_LIBRARIES}
${OGG_LIB}
${VORBIS_LIB}
vorbisenc
${VORBISENC_LIB}
${VORBISFILE_LIB}
${SNDFILE_LIB}
)

Expand Down
32 changes: 20 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
### sf3convert
# sf3convert

Utilities for SoundFont files.
Utilities for converting Soundfont files from version 2 to version 3 and back from version 3 to version 2.

* compress sound font files with ogg vorbis for use with [MuseScore](http://musescore.org)
* convert to "C" for embedding
### Sf3 format

The sf3 format stores compressed data (OGG vorbis files) instead of raw data (WAVE) in a soundfont. There is thus a **loss in quality** but the resulting files are lighter and more prone to be **embedded**. This format has been primarily designed and used by [MuseScore](http://musescore.org) and is now supported by other projects:

* [Calf-Fluidsynth](http://calf-studio-gear.org/)
* [Carla](http://kxstudio.linuxaudio.org/Applications:Carla)
* [LMMS](https://lmms.io)
* [Polyphone](https://www.polyphone-soundfonts.com)
* [Qsynth](https://qsynth.sourceforge.io)
* [Qtractor](https://qtractor.sourceforge.io)

**The compressed soundfont has the major version number 3. It is non standard and no specifications have been written yet**


### Compilation
Expand All @@ -14,21 +24,19 @@ Utilities for SoundFont files.
* libsdnfile
* libogg
* libvorbis
* libvorbisenc
* libvorbisfile

```
$ make release
```

### Usage Example:

This compresses the Fluid sound font from 148 MBytes to 20 MBytes.

sf3convert -z FluidR3.SF2 mops.sf3
This compresses the Fluid soundfont from 148 MBytes to 20 MBytes.

**The compressed sound font has the major version number 3. Its non standard
and can be used only (so far) by [MuseScore](http://musescore.org).**
sf3convert -z FluidR3.SF2 compressed_soundfont.sf3

This uncompresses a soundfont

### TODO:
Stereo samples are compressed as two single streams instead of compressing
them as stereo ogg vorbis streams. This may be less optimal.
sf3convert -y compressed_soundfont.sf3 FluidR3.sf2
10 changes: 7 additions & 3 deletions sf3convert.1
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
.Nd SoundFont conversion utility
.Sh SYNOPSIS
.Nm
.Op Fl cdsxz
.Op Fl cdsxyz
.Op Fl a Ar ampl
.Op Fl p Ar pres
.Op Fl S Ar number
Expand All @@ -20,7 +20,8 @@
The
.Nm
utility converts an SF2 format SoundFont; it can compress it
into SF3, encode as C for embedding into a binary, or as XML.
into SF3, uncompress from SF3, encode as C for embedding into a binary,
or as XML.
.Pp
The options are as follows:
.Bl -tag -width xxx
Expand Down Expand Up @@ -49,13 +50,16 @@ as the OGG stream serial number instead of a time-based random one.
Create a small soundfont (one instrument/preset), pan to 0.
.It Fl x
Output XML.
.It Fl y
Uncompress the soundfont.
.It Fl z
Compress the soundfont.
.El
.Pp
The
.Fl c ,
.Fl d
.Fl d ,
.Fl y
and
.Fl z
options are mutually exclusive.
Expand Down
35 changes: 28 additions & 7 deletions sfconvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
#include <QtCore/QTime>
#include "sfont.h"

bool smallSf = false;

//---------------------------------------------------------
// usage
//---------------------------------------------------------
Expand All @@ -38,6 +36,7 @@ static void usage(const char* pname)
fprintf(stderr, " -z compress sf\n");
fprintf(stderr, " -q qq ogg quality\n");
fprintf(stderr, " -a nn amplification in dB before ogg compression\n");
fprintf(stderr, " -y uncompress sf\n");
fprintf(stderr, " -x xml output\n");
fprintf(stderr, " -c c output\n");
fprintf(stderr, " -p nn preset\n");
Expand All @@ -56,6 +55,8 @@ int main(int argc, char* argv[])
bool code = false;
bool dump = false;
bool compress = false;
bool uncompress = false;
bool smallSf = false;
double oggQuality = 0.3;
double oggAmp = -1.0;
qint64 oggSerial = std::numeric_limits<qint64>::max();
Expand All @@ -67,7 +68,7 @@ int main(int argc, char* argv[])
fprintf(stderr, "%s: convert sound file\n", argv[0]);

int c;
while ((c = getopt(argc, argv, "xcp:dS:szq:a:")) != EOF) {
while ((c = getopt(argc, argv, "xcp:dS:syzq:a:")) != EOF) {
switch(c) {
case 'x':
xml = true;
Expand All @@ -87,6 +88,9 @@ int main(int argc, char* argv[])
case 's':
smallSf = true;
break;
case 'y':
uncompress = true;
break;
case 'z':
compress = true;
break;
Expand All @@ -113,12 +117,18 @@ int main(int argc, char* argv[])
usage(pname);
exit(3);
}
if (!xml && !code && !dump && !compress) {
if (!xml && !code && !dump && !compress && !uncompress) {
usage(pname);
exit(4);
}
if (compress && uncompress) {
usage(pname)
exit(5)
}

SoundFont sf(argv[0]);
SfTools::SoundFont sf(argv[0]);
if (smallSf)
sf.smallSf = true;

if (!sf.read()) {
fprintf(stderr, "sf read error\n");
Expand All @@ -142,10 +152,21 @@ int main(int argc, char* argv[])
if (xml)
sf.writeXml(&fo);
else
sf.write(&fo, oggQuality, oggAmp, oggSerial);
sf.compress(&fo, oggQuality, oggAmp, oggSerial);
fo.close();
}
else if (uncompress) {
QFile fo(argv[1]);
if (!fo.open(QIODevice::WriteOnly)) {
fprintf(stderr, "cannot open <%s>\n", argv[2]);
exit(2);
}
if (xml)
sf.writeXml(&fo);
else
sf.uncompress(&fo);
fo.close();
}
qDebug("Soundfont converted in: %d ms", t.elapsed());
return 0;
}

Loading