Looped SFZ instruments
Moderators: MattKingUSA, khz
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Looped SFZ instruments
I've tried to put just loop_mode=loop_continuous but LinuxSampler refuses to loop this. Does this mean I need full info inside WAV or manually specify start and end in SFZ?
Re: Looped SFZ instruments
Obviously that isn't the case.
So either include start and end...
... or get a good wave editor that allows you to set/save loop points (not Audacity -- it deletes them), with a (preferably 50%) crossfade algorithm (Waveosaur).
Author of BackupBand at https://sourceforge.net/projects/backupband/files/
My fans show their support by mentioning my name in their signature.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: Looped SFZ instruments
Wavosaur is Windows only.j_e_f_f_g wrote:... or get a good wave editor that allows you to set/save loop points (not Audacity -- it deletes them), with a (preferably 50%) crossfade algorithm (Waveosaur).
Re: Looped SFZ instruments
And it's also the single best tool for looping waves I've ever used. I'd advise you to try to get it running under Wine first, before wasting time on inferior tools.Lyberta wrote:Wavosaur is Windows only.
Author of BackupBand at https://sourceforge.net/projects/backupband/files/
My fans show their support by mentioning my name in their signature.
- bhilmers
- Established Member
- Posts: 229
- Joined: Mon Apr 23, 2012 11:44 pm
- Has thanked: 5 times
- Been thanked: 17 times
Re: Looped SFZ instruments
Ditto. Wavosaur is the best free audio editor I've ever used and it's been running perfectly in WINE for several years. I do most of my editing with it. The project is on the verge of abandonware and I hope the authors release the source.j_e_f_f_g wrote:And it's also the single best tool for looping waves I've ever used. I'd advise you to try to get it running under Wine first, before wasting time on inferior tools.Lyberta wrote:Wavosaur is Windows only.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: Looped SFZ instruments
Re: Looped SFZ instruments
Maybe a little overdone, but i would recommend polyphone. You can loop inside the programm and export wav, sf2 and sfz.
-
- Established Member
- Posts: 538
- Joined: Wed Oct 22, 2008 9:05 pm
- Has thanked: 35 times
- Been thanked: 94 times
- Contact:
Re: Looped SFZ instruments
Always use external meta data, in this case sfz loop.
-
- Established Member
- Posts: 681
- Joined: Sat Nov 01, 2014 8:15 pm
- Location: The Internet
- Been thanked: 1 time
Re: Looped SFZ instruments
Argh, it had Debian Stable build but it is too old for my Debian Testing.antiesen wrote:I welcome the attitude not to use system-foreign programs To your first question:
Maybe a little overdone, but i would recommend polyphone. You can loop inside the programm and export wav, sf2 and sfz.
Ok, it uses JUCE to read the chucks. That's fine but at this moment I'm not very interested in reading through JUCE (there are also license problems, right?).falkTX wrote:This part of SFZero references Loop0Start and Loop0End.
https://github.com/altalogix/SFZeroModu ... le.cpp#L27
Sure but I need to support those to fully support the SFZ format.nilshi wrote:Do not use the .wav built-in loop format. It is very fragile and practically not supported.
Always use external meta data, in this case sfz loop.
Ok, here's a single period of 440Hz sine wave, just 99 frames. Can someone put loop start at frame 0 and loop end at frame 99? Then I will figure out how to read this file with hex editor and C++.
- Attachments
-
- sine440_int16_stereo.wav
- (444 Bytes) Downloaded 80 times
Re: Looped SFZ instruments
Then another one with differet loop-settings an one with changed root-key and detuning.
- Attachments
-
- sine440_int16_stereo_LS0_LE99_RootKey64_Cent0.wav
- (514 Bytes) Downloaded 90 times
-
- sine440_int16_stereo_LS33_LE66_RootKey64_Cent0.wav
- (514 Bytes) Downloaded 91 times
-
- sine440_int16_stereo_LS33_LE66_RootKey52_Cent50.wav
- (514 Bytes) Downloaded 82 times
Re: Looped SFZ instruments
Code: Select all
#ifndef O_NOATIME
#define O_NOATIME 01000000
#endif
#pragma pack(1)
/////////////////////// WAVE File Stuff /////////////////////
// An IFF file header looks like this
typedef struct
{
unsigned char ID[4]; // could be {'R', 'I', 'F', 'F'} or {'F', 'O', 'R', 'M'}
uint32_t Length; // Length of subsequent file (including remainder of header). This is in
// Intel reverse byte order if RIFF, Motorola format if FORM.
unsigned char Type[4]; // {'W', 'A', 'V', 'E'} or {'A', 'I', 'F', 'F'}
} FILE_head;
// An IFF chunk header looks like this
typedef struct
{
unsigned char ID[4]; // 4 ascii chars that is the chunk ID
uint32_t Length; // Length of subsequent data within this chunk. This is in Intel reverse byte
// order if RIFF, Motorola format if FORM. Note: this doesn't include any
// extra byte needed to pad the chunk out to an even size.
} CHUNK_head;
// WAVE fmt chunk
typedef struct {
short wFormatTag;
unsigned short wChannels;
uint32_t dwSamplesPerSec;
uint32_t dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short wBitsPerSample;
// Note: there may be additional fields here, depending upon wFormatTag
} FORMAT;
typedef struct {
FILE_head head;
CHUNK_head fmt;
FORMAT fmtdata;
} WAVESTART;
// WAVE Sample Loop struct
typedef struct
{
int32_t dwIdentifier;
int32_t dwType;
uint32_t dwStart;
uint32_t dwEnd;
int32_t dwFraction;
int32_t dwPlayCount;
} SAMPLELOOP;
// WAVE Smpl chunk
typedef struct
{
int32_t dwManufacturer;
int32_t dwProduct;
int32_t dwSamplePeriod;
int32_t dwMIDIUnityNote;
int32_t dwMIDIPitchFraction;
int32_t dwSMPTEFormat;
int32_t dwSMPTEOffset;
int32_t cSampleLoops;
int32_t cbSamplerData;
} SAMPLER;
typedef struct {
int32_t dwIdentifier;
uint32_t dwPosition;
unsigned char fccChunk[4];
uint32_t dwChunkStart;
uint32_t dwBlockStart;
uint32_t dwSampleOffset;
} CUELOOP;
#pragma pack()
static const unsigned char Cue[4] = { 'c', 'u', 'e', ' ' };
static const unsigned char Smpl[4] = { 's', 'm', 'p', 'l' };
static const unsigned char Data[4] = { 'd', 'a', 't', 'a' };
/********************** compareID() *********************
* Compares the passed ID str (ie, a ptr to 4 Ascii
* bytes) with the ID at the passed ptr. Returns TRUE if
* a match, FALSE if not.
*/
static unsigned char compareID(const unsigned char * id, unsigned char * ptr)
{
register unsigned char i = 4;
while (i--)
{
if ( *(id)++ != *(ptr)++ ) return 0;
}
return 1;
}
typedef struct {
uint32_t DataLength;
uint32_t LoopStart;
uint32_t LoopEnd;
} MY_WAVE_INFO;
uint32_t readWave(const char * fn)
{
WAVESTART file;
FILE_head head;
MY_WAVE_INFO myInfo;
uint32_t action;
register int inHandle;
// Open the WAVE
inHandle = open(fn, O_RDONLY|O_NOATIME);
// Read in IFF File header and fmt chunk
read(inHandle, &file, sizeof(WAVESTART));
// Assume no loop
myInfo.LoopStart = myInfo.LoopEnd = (uint32_t)-1;
myInfo.DataLength = 0;
// Skip any extra fmt bytes
head.Length = file.fmt.Length - sizeof(FORMAT);
goto skip;
while (read(inHandle, &head, sizeof(CHUNK_head)) == sizeof(CHUNK_head))
{
// ============================ Is it a data chunk? ===============================
if (compareID(&Data[0], &head.ID[0]))
{
read(inHandle, wavePtr, head.Length);
myInfo.DataLength = head.Length;
}
// ============================ Is it an smpl chunk? ===============================
else if (compareID(&Smpl[0], &head.ID[0]))
{
SAMPLER smpl;
SAMPLELOOP smploop;
// Read in SAMPLER
read(inHandle, &smpl, sizeof(SAMPLER));
head.Length -= sizeof(SAMPLER);
// Use only the first loop
if (smpl.cSampleLoops)
{
// Read in sample loop
read(inHandle, &smploop, sizeof(SAMPLELOOP));
myInfo.LoopStart = smploop.dwStart;
myInfo.LoopEnd = smploop.dwEnd;
head.Length -= sizeof(SAMPLELOOP);
}
// Skip remainder of chunk
goto skip;
}
// ============================ Is it a cue chunk? ===============================
else if (compareID(&Cue[0], &head.ID[0]))
{
// Give preference to the smpl chunk if we found one
if (myInfo.LoopStart == (uint32_t)-1)
{
CUELOOP cueloop;
// Read in dwCuePoints
read(inHandle, &action, sizeof(uint32_t));
head.Length -= sizeof(uint32_t);
// Use only the first loop
if (action)
{
// Read in cue loop
read(inHandle, &cueloop, sizeof(CUELOOP));
myInfo.LoopStart = cueloop.dwPosition * (file.fmtdata.wBitsPerSample == 16 ? 2 : 4); // note: We don't care about 8-bit files
myInfo.LoopEnd = myInfo.DataLength / file.fmtdata.wChannels;
head.Length -= sizeof(CUELOOP);
}
}
// Skip remainder of chunk
goto skip;
}
// ============================ Skip this chunk ===============================
else
{
skip: if (head.Length & 1) ++head.Length; // If odd, round it up to account for pad byte
lseek(inHandle, head.Length, SEEK_CUR);
}
}
// We got the data? Note: size in bytes
if (myInfo.DataLength && myInfo.LoopStart != (uint32_t)-1)
{
// Offsets in bytes
myInfo.LoopStart *= ((file.fmtdata.wBitsPerSample == 16 ? 2 : 4) * file.fmtdata.wChannels);
myInfo.LoopEnd *= ((file.fmtdata.wBitsPerSample == 16 ? 2 : 4) * file.fmtdata.wChannels);
if (myInfo.LoopStart != myInfo.LoopEnd && myInfo.LoopStart < myInfo.DataLength)
{
if (myInfo.LoopEnd > myInfo.DataLength) myInfo.LoopEnd = myInfo.DataLength;
if (myInfo.LoopStart > myInfo.LoopEnd)
{
register uint32_t temp;
temp = myInfo.LoopEnd;
myInfo.LoopEnd = myInfo.LoopStart;
myInfo.LoopStart = temp;
}
}
}
close(inHandle);
}
Author of BackupBand at https://sourceforge.net/projects/backupband/files/
My fans show their support by mentioning my name in their signature.
Re: Looped SFZ instruments
Author of BackupBand at https://sourceforge.net/projects/backupband/files/
My fans show their support by mentioning my name in their signature.
Re: Looped SFZ instruments
I wrote it. It originally came from a Windows utility i wrote/released two decades ago called Aiff2Wav (convert between WAVE and apple AIFF formats), and has been subsequently used in many of my other projects, most recently BackupBand's ConvertWave utility. The latter is GPL. (Considering BSD going forward, because the "amateur gpl licensing police" have become more of an actual, real-world annoyance than anyone who has ever "borrowed" my code. Seriously.) But the above snippet is so utterly basic, simple, short, and limited in scope that i consider it public domain. It would be the epitome of hubris for a developer to think the above snippet should merit copyright. And i ain't one of those a-holes.falkTX wrote:We cant just borrow code like that... what license is that in?
Where did it came from, did you wrote it yourself or copied from somewhere else?
If someone wants it, use it.
Author of BackupBand at https://sourceforge.net/projects/backupband/files/
My fans show their support by mentioning my name in their signature.