253 |
file_is_changed = false; |
file_is_changed = false; |
254 |
|
|
255 |
show_all_children(); |
show_all_children(); |
256 |
|
|
257 |
|
// start with a new gig file by default |
258 |
|
on_action_file_new(); |
259 |
} |
} |
260 |
|
|
261 |
MainWindow::~MainWindow() |
MainWindow::~MainWindow() |
579 |
int bitdepth; |
int bitdepth; |
580 |
switch (info.format & 0xff) { |
switch (info.format & 0xff) { |
581 |
case SF_FORMAT_PCM_S8: |
case SF_FORMAT_PCM_S8: |
|
bitdepth = 16; // we simply convert to 16 bit for now |
|
|
break; |
|
582 |
case SF_FORMAT_PCM_16: |
case SF_FORMAT_PCM_16: |
583 |
|
case SF_FORMAT_PCM_U8: |
584 |
bitdepth = 16; |
bitdepth = 16; |
585 |
break; |
break; |
586 |
case SF_FORMAT_PCM_24: |
case SF_FORMAT_PCM_24: |
|
bitdepth = 32; // we simply convert to 32 bit for now |
|
|
break; |
|
587 |
case SF_FORMAT_PCM_32: |
case SF_FORMAT_PCM_32: |
|
bitdepth = 32; |
|
|
break; |
|
|
case SF_FORMAT_PCM_U8: |
|
|
bitdepth = 16; // we simply convert to 16 bit for now |
|
|
break; |
|
588 |
case SF_FORMAT_FLOAT: |
case SF_FORMAT_FLOAT: |
|
bitdepth = 32; |
|
|
break; |
|
589 |
case SF_FORMAT_DOUBLE: |
case SF_FORMAT_DOUBLE: |
590 |
bitdepth = 32; // I guess we will always truncate this to 32 bit |
bitdepth = 24; |
591 |
break; |
break; |
592 |
default: |
default: |
593 |
sf_close(hFile); // close sound file |
sf_close(hFile); // close sound file |
594 |
throw std::string("format not supported"); // unsupported subformat (yet?) |
throw std::string("format not supported"); // unsupported subformat (yet?) |
595 |
} |
} |
596 |
// allocate appropriate copy buffer (TODO: for now we copy |
|
597 |
// it in one piece, might be tough for very long samples) |
const int bufsize = 10000; |
|
// and copy sample data into buffer |
|
|
int8_t* buffer = NULL; |
|
598 |
switch (bitdepth) { |
switch (bitdepth) { |
599 |
case 16: |
case 16: { |
600 |
buffer = new int8_t[2 * info.channels * info.frames]; |
short* buffer = new short[bufsize * info.channels]; |
601 |
// libsndfile does the conversion for us (if needed) |
sf_count_t cnt = info.frames; |
602 |
sf_readf_short(hFile, (short*) buffer, info.frames); |
while (cnt) { |
603 |
|
// libsndfile does the conversion for us (if needed) |
604 |
|
int n = sf_readf_short(hFile, buffer, bufsize); |
605 |
|
// write from buffer directly (physically) into .gig file |
606 |
|
iter->gig_sample->Write(buffer, n); |
607 |
|
cnt -= n; |
608 |
|
} |
609 |
|
delete[] buffer; |
610 |
break; |
break; |
611 |
case 32: |
} |
612 |
buffer = new int8_t[4 * info.channels * info.frames]; |
case 24: { |
613 |
// libsndfile does the conversion for us (if needed) |
int* srcbuf = new int[bufsize * info.channels]; |
614 |
sf_readf_int(hFile, (int*) buffer, info.frames); |
uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels]; |
615 |
|
sf_count_t cnt = info.frames; |
616 |
|
while (cnt) { |
617 |
|
// libsndfile returns 32 bits, convert to 24 |
618 |
|
int n = sf_readf_int(hFile, srcbuf, bufsize); |
619 |
|
int j = 0; |
620 |
|
for (int i = 0 ; i < n * info.channels ; i++) { |
621 |
|
dstbuf[j++] = srcbuf[i] >> 8; |
622 |
|
dstbuf[j++] = srcbuf[i] >> 16; |
623 |
|
dstbuf[j++] = srcbuf[i] >> 24; |
624 |
|
} |
625 |
|
// write from buffer directly (physically) into .gig file |
626 |
|
iter->gig_sample->Write(dstbuf, n); |
627 |
|
cnt -= n; |
628 |
|
} |
629 |
|
delete[] srcbuf; |
630 |
|
delete[] dstbuf; |
631 |
break; |
break; |
632 |
|
} |
633 |
} |
} |
|
// write from buffer directly (physically) into .gig file |
|
|
(*iter).gig_sample->Write(buffer, info.frames); |
|
634 |
// cleanup |
// cleanup |
635 |
sf_close(hFile); |
sf_close(hFile); |
|
delete[] buffer; |
|
636 |
// on success we remove the sample from the import queue, |
// on success we remove the sample from the import queue, |
637 |
// otherwise keep it, maybe it works the next time ? |
// otherwise keep it, maybe it works the next time ? |
638 |
std::list<SampleImportItem>::iterator cur = iter; |
std::list<SampleImportItem>::iterator cur = iter; |
724 |
entry[15].set_text(info->Subject); |
entry[15].set_text(info->Subject); |
725 |
} |
} |
726 |
|
|
727 |
|
void InstrumentProps::add_prop(BoolEntry& boolentry) |
728 |
|
{ |
729 |
|
table.attach(boolentry.widget, 0, 2, rowno, rowno + 1, |
730 |
|
Gtk::FILL, Gtk::SHRINK); |
731 |
|
rowno++; |
732 |
|
boolentry.signal_changed_by_user().connect(instrument_changed.make_slot()); |
733 |
|
} |
734 |
|
|
735 |
|
void InstrumentProps::add_prop(BoolEntryPlus6& boolentry) |
736 |
|
{ |
737 |
|
table.attach(boolentry.widget, 0, 2, rowno, rowno + 1, |
738 |
|
Gtk::FILL, Gtk::SHRINK); |
739 |
|
rowno++; |
740 |
|
boolentry.signal_changed_by_user().connect(instrument_changed.make_slot()); |
741 |
|
} |
742 |
|
|
743 |
void InstrumentProps::add_prop(LabelWidget& prop) |
void InstrumentProps::add_prop(LabelWidget& prop) |
744 |
{ |
{ |
745 |
table.attach(prop.label, 0, 1, rowno, rowno + 1, |
table.attach(prop.label, 0, 1, rowno, rowno + 1, |
754 |
: table(2,1), |
: table(2,1), |
755 |
quitButton(Gtk::Stock::CLOSE), |
quitButton(Gtk::Stock::CLOSE), |
756 |
eName("Name"), |
eName("Name"), |
757 |
eIsDrum("IsDrum"), |
eIsDrum("Is drum"), |
758 |
eMIDIBank("MIDIBank", 0, 16383), |
eMIDIBank("MIDI bank", 0, 16383), |
759 |
eMIDIProgram("MIDIProgram"), |
eMIDIProgram("MIDI program"), |
760 |
eAttenuation("Attenuation", 0, 96, 0, 1), |
eAttenuation("Attenuation", 0, 96, 0, 1), |
761 |
eGainPlus6("Gain +6dB", eAttenuation, -6), |
eGainPlus6("Gain +6dB", eAttenuation, -6), |
762 |
eEffectSend("EffectSend", 0, 65535), |
eEffectSend("Effect send", 0, 65535), |
763 |
eFineTune("FineTune", -8400, 8400), |
eFineTune("Fine tune", -8400, 8400), |
764 |
ePitchbendRange("PitchbendRange", 0, 12), |
ePitchbendRange("Pitchbend range", 0, 12), |
765 |
ePianoReleaseMode("PianoReleaseMode"), |
ePianoReleaseMode("Piano release mode"), |
766 |
eDimensionKeyRangeLow("DimensionKeyRangeLow"), |
eDimensionKeyRangeLow("Dimension key range low"), |
767 |
eDimensionKeyRangeHigh("DimensionKeyRangeHigh") |
eDimensionKeyRangeHigh("Dimension key range high") |
768 |
{ |
{ |
769 |
set_title("Instrument properties"); |
set_title("Instrument properties"); |
770 |
|
|
1055 |
dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK); |
dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK); |
1056 |
dialog.set_select_multiple(true); |
dialog.set_select_multiple(true); |
1057 |
Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile |
Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile |
1058 |
const char* supportedFileTypes[] = { |
const char* const supportedFileTypes[] = { |
1059 |
"*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd", |
"*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd", |
1060 |
"*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF", |
"*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF", |
1061 |
"*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64", |
"*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64", |
1085 |
int bitdepth; |
int bitdepth; |
1086 |
switch (info.format & 0xff) { |
switch (info.format & 0xff) { |
1087 |
case SF_FORMAT_PCM_S8: |
case SF_FORMAT_PCM_S8: |
|
bitdepth = 16; // we simply convert to 16 bit for now |
|
|
break; |
|
1088 |
case SF_FORMAT_PCM_16: |
case SF_FORMAT_PCM_16: |
1089 |
|
case SF_FORMAT_PCM_U8: |
1090 |
bitdepth = 16; |
bitdepth = 16; |
1091 |
break; |
break; |
1092 |
case SF_FORMAT_PCM_24: |
case SF_FORMAT_PCM_24: |
|
bitdepth = 32; // we simply convert to 32 bit for now |
|
|
break; |
|
1093 |
case SF_FORMAT_PCM_32: |
case SF_FORMAT_PCM_32: |
|
bitdepth = 32; |
|
|
break; |
|
|
case SF_FORMAT_PCM_U8: |
|
|
bitdepth = 16; // we simply convert to 16 bit for now |
|
|
break; |
|
1094 |
case SF_FORMAT_FLOAT: |
case SF_FORMAT_FLOAT: |
|
bitdepth = 32; |
|
|
break; |
|
1095 |
case SF_FORMAT_DOUBLE: |
case SF_FORMAT_DOUBLE: |
1096 |
bitdepth = 32; // I guess we will always truncate this to 32 bit |
bitdepth = 24; |
1097 |
break; |
break; |
1098 |
default: |
default: |
1099 |
sf_close(hFile); // close sound file |
sf_close(hFile); // close sound file |
1102 |
// add a new sample to the .gig file |
// add a new sample to the .gig file |
1103 |
gig::Sample* sample = file->AddSample(); |
gig::Sample* sample = file->AddSample(); |
1104 |
// file name without path |
// file name without path |
1105 |
sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw(); |
Glib::ustring filename = Glib::filename_display_basename(*iter); |
1106 |
|
// remove file extension if there is one |
1107 |
|
for (int i = 0; supportedFileTypes[i]; i++) { |
1108 |
|
if (Glib::str_has_suffix(filename, supportedFileTypes[i] + 1)) { |
1109 |
|
filename.erase(filename.length() - strlen(supportedFileTypes[i] + 1)); |
1110 |
|
break; |
1111 |
|
} |
1112 |
|
} |
1113 |
|
sample->pInfo->Name = filename; |
1114 |
sample->Channels = info.channels; |
sample->Channels = info.channels; |
1115 |
sample->BitDepth = bitdepth; |
sample->BitDepth = bitdepth; |
1116 |
sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels; |
sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels; |
1117 |
sample->SamplesPerSecond = info.samplerate; |
sample->SamplesPerSecond = info.samplerate; |
1118 |
|
sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond; |
1119 |
|
sample->BlockAlign = sample->FrameSize; |
1120 |
|
sample->SamplesTotal = info.frames; |
1121 |
|
|
1122 |
|
SF_INSTRUMENT instrument; |
1123 |
|
if (sf_command(hFile, SFC_GET_INSTRUMENT, |
1124 |
|
&instrument, sizeof(instrument)) != SF_FALSE) |
1125 |
|
{ |
1126 |
|
sample->MIDIUnityNote = instrument.basenote; |
1127 |
|
|
1128 |
|
if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) { |
1129 |
|
sample->Loops = 1; |
1130 |
|
|
1131 |
|
switch (instrument.loops[0].mode) { |
1132 |
|
case SF_LOOP_FORWARD: |
1133 |
|
sample->LoopType = gig::loop_type_normal; |
1134 |
|
break; |
1135 |
|
case SF_LOOP_BACKWARD: |
1136 |
|
sample->LoopType = gig::loop_type_backward; |
1137 |
|
break; |
1138 |
|
case SF_LOOP_ALTERNATING: |
1139 |
|
sample->LoopType = gig::loop_type_bidirectional; |
1140 |
|
break; |
1141 |
|
} |
1142 |
|
sample->LoopStart = instrument.loops[0].start; |
1143 |
|
sample->LoopEnd = instrument.loops[0].end; |
1144 |
|
sample->LoopPlayCount = instrument.loops[0].count; |
1145 |
|
sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1; |
1146 |
|
} |
1147 |
|
} |
1148 |
|
|
1149 |
// schedule resizing the sample (which will be done |
// schedule resizing the sample (which will be done |
1150 |
// physically when File::Save() is called) |
// physically when File::Save() is called) |
1151 |
sample->Resize(info.frames); |
sample->Resize(info.frames); |
1161 |
Gtk::TreeModel::iterator iterSample = |
Gtk::TreeModel::iterator iterSample = |
1162 |
m_refSamplesTreeModel->append(row.children()); |
m_refSamplesTreeModel->append(row.children()); |
1163 |
Gtk::TreeModel::Row rowSample = *iterSample; |
Gtk::TreeModel::Row rowSample = *iterSample; |
1164 |
rowSample[m_SamplesModel.m_col_name] = sample->pInfo->Name.c_str(); |
rowSample[m_SamplesModel.m_col_name] = filename; |
1165 |
rowSample[m_SamplesModel.m_col_sample] = sample; |
rowSample[m_SamplesModel.m_col_sample] = sample; |
1166 |
rowSample[m_SamplesModel.m_col_group] = NULL; |
rowSample[m_SamplesModel.m_col_group] = NULL; |
1167 |
// close sound file |
// close sound file |
1263 |
const Glib::RefPtr<Gdk::DragContext>& context, int, int, |
const Glib::RefPtr<Gdk::DragContext>& context, int, int, |
1264 |
const Gtk::SelectionData& selection_data, guint, guint time) |
const Gtk::SelectionData& selection_data, guint, guint time) |
1265 |
{ |
{ |
|
gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion(); |
|
1266 |
gig::Sample* sample = *((gig::Sample**) selection_data.get_data()); |
gig::Sample* sample = *((gig::Sample**) selection_data.get_data()); |
1267 |
|
|
1268 |
if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) { |
if (sample && selection_data.get_length() == sizeof(gig::Sample*)) { |
1269 |
if (sample != dimregion->pSample) { |
if (dimreg_edit.set_sample(sample)) { |
|
dimregion->pSample = sample; |
|
|
dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str()); |
|
1270 |
std::cout << "Drop received sample \"" << |
std::cout << "Drop received sample \"" << |
1271 |
dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl; |
sample->pInfo->Name << "\"" << std::endl; |
1272 |
// drop success |
// drop success |
1273 |
context->drop_reply(true, time); |
context->drop_reply(true, time); |
|
file_changed(); |
|
1274 |
return; |
return; |
1275 |
} |
} |
1276 |
} |
} |