/* Spectroscopic Toolkit version 1.95 by Pieter Suurmond, april 21, 2011. Copyright (c) 2000-2011 - Pieter Suurmond Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Any person wishing to distribute modifications to the Software is requested to send the modifications to the original developer so that they can be incorporated into the canonical version. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Using the binary database-file 'gfall.pbin', produced by the 'pconv'-program that reads Robert Kurucz's latest data file. More Hydrogen studies (based on earlier ST.c03_H). */ #include /* Standard headers. */ #include #include #include #include "ST_wavelets.h" /* Prototype addWAVELET(). */ #include "ST_pconv.h" #include "c06_JEBASE.h" /* Small database in mem for easier line-access. */ /* Object c06_HBASE.o must be linked for Hsplit. */ #include "c00.h" /*---------------------------------------------------------------------------------------------*/ short c06_Hbells(ENGINEp E, FILE* msg) { JDIF_SERIES* hseries; pieterPacked *hline; derivedData more; /* See ST.gfall.pbin.c. */ unsigned long ampSkipped = 0, frqSkipped = 0; short e = 0; double a; long double top, dur, audioHertz; /*------------------------------------------------------------ Frequency & time transpositions: */ long double transpositionRatio = pow(2.0, -40.0); /* 40 octaves down. */ /*------------------------------------------------------------ Smoother frequency windowing: */ long double lowestFreq = 20.0; /* (trapeziod instead of brickwall) */ long double aboveLowestFreq = 1.25 * lowestFreq; /* Rise to 1 within 1 major third. */ long double aboveHertz = aboveLowestFreq - lowestFreq; long double nyquist = 0.5*(double)getSamplerateENGINE(E); long double belowNyquist = nyquist / 1.2; /* Fall to 0 within 1 minor third. */ long double belowHertz = nyquist - belowNyquist; /*-----------------------------------------------------------------------------------------------*/ int dj, lj, le, de; /* Coordinates in JEBASE. */ short bell; hseries = init_JEBASE(msg); /* Some sorted hydrogen-lines. */ if (!hseries) { if (msg) fprintf(msg, "init_JEBASE() failed!\n"); return 1; } dj = 0; /* dj not varied. */ for (bell = 0; bell < 24; bell++) /* Play bells 0 to 23 inclusive. */ { /*---------------------------------------------------*/ for (lj=0; ljJLOWseries[dj].numJLOW; lj++) { for (le=0; leJLOWseries[dj].ELOWseries[lj].numELOW; le++) { de = hseries->JLOWseries[dj].ELOWseries[lj].EDIFseries[le].numEDIF - 1 - bell; if (msg) fprintf(msg, "Hydrogen bell #%d: dj=%d lj=%d le=%d de=%d.\n", bell, dj, lj, le, de); hline = ask_JEBASE(hseries, dj, lj, le, de); /* Try to obtain line data. */ if (hline) { moreLineData(hline, &more); /* Derive some more. */ printLineEssential(hline, msg); /* printLineDerived(&more, msg); */ audioHertz = more.frequency * transpositionRatio; /* Transpose. */ if ((audioHertz >= lowestFreq) && (audioHertz <= nyquist)) { /*-------------------------------------------- Less brickwall: ---*/ if (audioHertz < aboveLowestFreq) a = (audioHertz - lowestFreq) / aboveHertz; /* Rise to 1 within 1 minor third. */ else if (audioHertz > belowNyquist) a = (nyquist - audioHertz) / belowHertz; /* Fall to 0 within 1 major third. */ else a = 1.0; /* ----------------- Amplitude: ------------------------------------*/ /* Compress amplitude-range (per section) by 5th-power-root. */ a *= 0.008 * pow(1.0e-12 * more.Avalue, 0.2); /* Lower freqs (lower lj) louder: */ a *= (double)(1 + lj); /* Lower bells (lower bell = higher de) louder: */ a *= (double)(4 + de); /*-------------------- Amplitude treshold (23 bit) ---------------*/ if (a >= 1.192093E-7) { top = 2.0 * bell; /* Bells 2 seconds apart. */ top += 0.01 * (double)lj; /* Lower freqs (lj) later. */ dur = 1.0 / (double)(4 + bell); /* Higher bells shorter. */ dur *= (double)(1 + lj); /* Lower freqs (lj) longer. */ /**** for (align=0; align< ***/ if (addWAVELET (E, msg, 0, /* frq */ audioHertz, /* amp */ a, /* pan */ 0.0, /* Center. */ /* top */ 20.0 + top, /* offset 20.0 seconds. */ /* dur */ dur, /* 1 second per line. */ /* env */ kENV_ExpDecay, /* pha */ 0)) /* 0 = sync with envelope. */ { if (msg) fprintf(msg, "Illegal wavelet (1)!\n"); e = 44; goto err; } } else { if (msg) fprintf(msg, "Skipping line dj=%d lj=%d le=%d de=%d (AMP too low).\n", dj, lj, le, de); ampSkipped++; } } else { if (msg) fprintf(msg, "Skipping line dj=%d lj=%d le=%d de=%d (FRQ=%.2Lf).\n", dj, lj, le, de, audioHertz); frqSkipped++; } } else if (msg) fprintf(msg, "ask_JEBASE(dj=%d lj=%d le=%d de=%d) = NULL !!!\n", dj, lj, le, de); } } /*---------------------------------------------------*/ } if (msg) { fprintf(msg, "Skipped %ld lines (AMP).\n", ampSkipped); fprintf(msg, "Skipped %ld lines (FRQ).\n", frqSkipped); } err: free_JEBASE(&hseries); /* Also clears referring variable. */ return e; } /*-----------------------------------------------------------------------------------*/ static short addHBell(short bell, /* Bell number 0 to 6 (or more?)..... */ short hep, /* 0 for H; 1 for He+. */ long double TOP, /* Starttime of exponential decay. */ double AMP, /* Linear amplitude. */ JDIF_SERIES* hseries, /* Allocated previously. */ ENGINEp E, FILE* msg) { pieterPacked *hline; derivedData more; /* See ST.gfall.pbin.c. */ short e = 0; char* txt; double pan, a; long double minidelay, dur, audioHertz; /*------------------------------------------------------------ Frequency & time transpositions: */ long double transpositionRatio = pow(2.0, -40.0); /* 40 octaves down. */ /*------------------------------------------------------------ Smoother frequency windowing: */ double lowestFreq = 20.0; /* (trapeziod instead of brickwall) */ double aboveLowestFreq = 1.25 * lowestFreq; /* Rise to 1 within 1 major third. */ double aboveHertz = aboveLowestFreq - lowestFreq; double nyquist = 0.5*(double)getSamplerateENGINE(E); double belowNyquist = nyquist / 1.2; /* Fall to 0 within 1 minor third. */ double belowHertz = nyquist - belowNyquist; /*-----------------------------------------------------------------------------------------------*/ int lj, le, de, dj = 0; /* Coordinates in JEBASE. */ if (hep) txt = "He+"; else txt = "H"; if (msg) fprintf(msg, "--- %s BELL #%d, AMP=%.4f:\n", txt, bell, AMP); for (lj=0; lj<5; /* USING ONLY 5 out of 12: hseries->JLOWseries[dj].numJLOW; */ lj++) { for (le=0; leJLOWseries[dj].ELOWseries[lj].numELOW; le++) { de = hseries->JLOWseries[dj].ELOWseries[lj].EDIFseries[le].numEDIF - 1 - bell; if (msg) fprintf(msg, "%s bell #%d: dj=%d lj=%d le=%d de=%d.\n", txt, bell, dj, lj, le, de); hline = ask_JEBASE(hseries, dj, lj, le, de); /* Try to obtain line data. */ if (hline) { moreLineData(hline, &more); /* Derive some more. */ printLineEssential(hline, msg); audioHertz = more.frequency * transpositionRatio; /* Transpose. */ if ((audioHertz >= lowestFreq) && (audioHertz <= nyquist)) { /*-------------------------------------------- Less brickwall: ---*/ if (audioHertz < aboveLowestFreq) a = (audioHertz - lowestFreq) / aboveHertz; /* Rise to 1 within 1 minor third. */ else if (audioHertz > belowNyquist) a = (nyquist - audioHertz) / belowHertz; /* Fall to 0 within 1 major third. */ else a = 1.0; /* ----------------- Amplitude: ------------------------------------*/ /* Compress amplitudes by taking 5th-power-root. */ a *= pow(1.0e-8 * more.Avalue, 0.2); /* Lower freqs (higher lj) louder: */ a *= (double)(1 + lj); /* Lower bells louder: */ a /= (double)((12 + bell) * (1 + hep)); /* Likewise duration. */ /* Argument from caller. */ a *= AMP; /*-------------------- Amplitude treshold (23 bit) -----------------*/ if (a >= 1.192093E-7) { /*---------------- Panning: ----------*/ pan = (0.20 * (bell - 3)) /* Panning #0 at left; 3 in center, 6 at right. */ - (0.02 * lj) + (0.01 * le) /* Little spreading. */ - 0.15 + (0.30 * hep); /* H slightly left; He+ slightly right. */ /*---------------- Duration: ---------*/ dur = 1.0 / (double)((12 + bell) * (1 + hep)); /* Higher bells shorter, He+ half length. */ dur *= (double)(2 + lj); /* Lower freqs (higher lj) longer. */ dur *= pow(20000.0 / audioHertz, 0.15); /* extra. */ minidelay = 0.5 / audioHertz; /* Half a period delay (50 Hz --> 10 ms). */ e = addWAVELET(E, msg, 0, /* frq */ audioHertz, /* amp */ a, /* pan */ pan, /* top */ TOP + minidelay, /* Starttime. */ /* dur */ dur, /* 1 second per line. */ /* env */ kENV_ExpDecay, /* pha */ 0); /* 0 = sync with envelope. */ if (e) { if (msg != NULL) fprintf(msg, "addWAVELET() = %d!\n", (int)e); return 44; } } else if (msg != NULL) fprintf(msg, "Skip line dj=%d lj=%d le=%d de=%d (AMP too low).\n", dj, lj, le, de); } else if (msg != NULL) fprintf(msg, "Skip line dj=%d lj=%d le=%d de=%d (FRQ=%.2Lf).\n", dj, lj, le, de, audioHertz); } else if (msg != NULL) fprintf(msg, "ask_JEBASE(dj=%d lj=%d le=%d de=%d) = NULL !!!\n", dj, lj, le, de); } } return e; } /*-----------------------------------------------------------------------------------------------*/ /* Hydrogen and Helium+ gamelan, 4*7 days. */ short c06_HHeP_bells(ENGINEp E, FILE* msg, long double start) { short t, e = 0; JDIF_SERIES *hseries, *hepseries; long double tick = (60.0 * 60.0) / 16384.0; /* One tick corresponds to 1 hour. */ long double tt; double amp = 1.0; /* 24 ticks corresponds to 1 day. */ #define kTicks (676) /* Total 3 + (4 * 168) + 1 ticks. */ char hi[] = "012\ \ 3 6 2 5 1 4 0 3 \ 6 2 5 1 4 0 3 6 \ 2 5 1 4 0 3 6 2 \ 5 1 4 0 3 6 2 5 \ 1 4 0 3 6 2 5 1 \ 4 0 3 6 2 5 1 4 \ 0 3 6 2 5 1 4 012\ \ 3 5 0 4 1 3 5 2 45\ 6 3 0 4 6 1 5 43\ 2 4 6 3 0 2 4 1 34\ 5 2 6 3 5 0 4 32\ 1 3 5 2 6 1 3 0 23\ 4 1 5 2 4 6 3 21\ 0 2 4 1 5 0 2 6 54\ \ 362 14 36 51 03 25 40362\ 614 36 51 03 25 40362 14\ 236 51 03 25 40362 14 36\ 51 03 25 40362 14 36 51\ 03 25 40362 14 36 51 03\ 425 40362 14 36 51 03 25\ 040362 14 36 51 03 25 40\ \ 3 6 2 5 1 4 0 3 \ 6 2 5 1 4 0 3 6 \ 2 5 1 4 0 3 6 2 \ 5 1 4 0 3 6 2 5 \ 1 4 0 3 6 2 5 1 \ 4 0 3 6 2 5 1 4 \ 0 3 6 2 5 1 4 0 \ \ 3"; char lo[] = " \ \ 3 0 4 1 5 2 \ 6 3 0 4 1 5 \ 2 6 3 0 4 1 \ 5 2 6 3 0 4 \ 1 5 2 6 3 0 \ 4 1 5 2 6 3 \ 0 4 1 5 2 6 \ \ 3 6 2 5 1 4 0 3 \ 6 2 5 1 4 0 3 6 \ 2 5 1 4 0 3 6 2 \ 5 1 4 0 3 6 2 5 \ 1 4 0 3 6 2 5 1 \ 4 0 3 6 2 5 1 4 \ 0 3 6 2 5 1 4 0 \ \ 3 6 2 5 1 4 0 3 \ 6 2 5 1 4 0 3 6 \ 2 5 1 4 0 3 6 2 \ 5 1 4 0 3 6 2 5 \ 1 4 0 3 6 2 5 1 \ 4 0 3 6 2 5 1 4 \ 0 3 6 2 5 1 4 0 \ \ 3 0 4 1 5 2 \ 6 3 0 4 1 5 \ 2 6 3 0 4 1 \ 5 2 6 3 0 4 \ 1 5 2 6 3 0 \ 4 1 5 2 6 3 \ 0 4 1 5 2 6 \ \ 3"; /* 673 chars. */ char a[] = "356\ \ 8 7 \ \ \ \ \ \ 67\ \ 8 \ \ \ \ \ \ \ \ 98 98 98 98 98 98 \ 98 98 98 98 98 98 \ 98 98 98 98 98 98 \ 98 98 98 98 98 98 \ 98 98 98 98 98 98 \ 98 98 98 98 98 98 \ 98 98 98 98 98 9876\ \ 8 \ \ \ \ \ \ \ \ 9"; if (msg != NULL) fprintf(msg, "Running c06_HHeP_bells()...\n"); if ((strlen(lo) != kTicks) || (strlen(hi) != kTicks) || (strlen(a) != kTicks)) { if (msg != NULL) fprintf(msg, "Array-lengths not ok!\n"); return 999; } hseries = init_JEBASE(msg); /* Some sorted hydrogen lines. */ if (!hseries) { if (msg != NULL) fprintf(msg, "init_JEBASE() failed!\n"); return 1; } hepseries = init_JEBASE_HeP(msg); /* Some sorted He+ lines. */ if (!hepseries) { free_JEBASE(&hseries); if (msg) fprintf(msg, "init_JEBASE_HeP() failed!\n"); return 1; } for (t = 0; t < kTicks; t++) { tt = start + ((long double)t * tick); if (a[t] != ' ') /* Amplitude for both voices. */ amp = 0.05 * (double)(11 + (a[t]-'0')); /* 0.55 .. 1.00. */ if (lo[t] != ' ') e |= addHBell(lo[t]-'0', 0, tt, 0.48 * amp, hseries, E, msg); if (hi[t] != ' ') e |= addHBell(hi[t]-'0', 1, tt, 0.30 * amp, hepseries, E, msg); } free_JEBASE(&hepseries); free_JEBASE(&hseries); /* Also clears referring variable. */ if (msg != NULL) fprintf(msg, "Finished c06_HHeP_bells().\n"); return e; } /*------------------------------------*/ short c06_HHe_bells(ENGINEp E, FILE* msg) { return c06_HHeP_bells(E, msg, 1.00); }