1 /*
2 gnauralnet_running.c
3 This should be the only place BinauralBeat.h variables are accessed
4 The point of this file is to contain only things that need BB vars.
5 Depends on:
6 gnauralnet.h
7 gnauralnet_clocksync.c
8 gnauralnet_lists.c
9 gnauralnet_main.c
10 gnauralnet_socket.c
11
12 Copyright (C) 2008 Bret Logan
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 */
28
29 #include "gnauralnet.h"
30 #include "BinauralBeat.h"
31
32 ////////////////////////////////////////
33 //this prepares various local vars that will be loaded as
34 //outgoing data in gnauralnet_main
35 //Gets called by GN_Time_ProcessOutgoingData
GN_Running_ProcessOutgoingData(GN_Friend * curFriend)36 void GN_Running_ProcessOutgoingData (GN_Friend * curFriend)
37 {
38 if (NULL == curFriend)
39 {
40 return;
41 }
42 GN_My.CurrentSampleCount = BB_CurrentSampleCount;
43 if (0 > BB_LoopCount)
44 {
45 GN_My.LoopCount = -1;
46 }
47 else
48 {
49 if (0x7fff > BB_LoopCount)
50 {
51 GN_My.LoopCount = BB_LoopCount;
52 }
53 else
54 {
55 GN_My.LoopCount = 0x7fff;
56 }
57 }
58 }
59
60 ////////////////////////////////////////
61 //Gets called by GN_Time_ProcessIncomingData
GN_Running_ProcessIncomingData(GN_Friend * curFriend)62 void GN_Running_ProcessIncomingData (GN_Friend * curFriend)
63 {
64 if (NULL == curFriend)
65 {
66 return;
67 }
68 /*
69 this will need to be in eventually:
70 if (0 == GN_My.RunningID || curFriend->RunningID != GN_My.RunningID)
71 {
72 return;
73 }
74 */
75 // unsigned int CurrentSampleCount;
76 // int LoopCount;
77 if (TRUE == BB_InCriticalLoopFlag)
78 {
79 GN_DBGOUT ("Not updating; BB in critical loop");
80 return;
81 }
82
83 if (curFriend->ScheduleFingerprint != GN_My.ScheduleFingerprint)
84 {
85 GN_DBGOUT_INT ("NOT Same schedule:", curFriend->ScheduleFingerprint);
86 GN_DBGOUT_INT (" Me:", GN_My.ScheduleFingerprint);
87 }
88 else
89 {
90 GN_DBGOUT_INT ("Same schedule:", GN_My.ScheduleFingerprint);
91 }
92
93 //need to actually implement this:
94 if (curFriend->RunningID != GN_My.RunningID)
95 {
96 GN_DBGOUT_INT ("NOT Same running:", curFriend->RunningID);
97 GN_DBGOUT_INT (" Me:", GN_My.RunningID);
98 }
99 else
100 {
101 GN_DBGOUT_INT ("Same running:", GN_My.RunningID);
102 }
103
104 //Now see if incoming data has seniority over mine:
105 curFriend->CurrentSampleCount_diff = BB_CurrentSampleCount -
106 curFriend->CurrentSampleCount;
107 if (curFriend->RunningSeniority >
108 (curFriend->Time_Recv.tv_sec - GN_My.RunningStartTime.tv_sec))
109 {
110 GN_DBGOUT_INT ("I Follow, sample diff:",
111 curFriend->CurrentSampleCount_diff);
112 BB_CurrentSampleCount = curFriend->CurrentSampleCount;
113 }
114 else
115 {
116 GN_DBGOUT_INT ("I Lead, sample diff:", curFriend->CurrentSampleCount_diff);
117 }
118 }
119
120 ////////////////////////////////////////////////////////////////
121 //A sort of low-grade PRNG seeded from major Schedule data features,
122 //in order to give a way to always return the same arbitrary number
123 //for a given schedule. 65k possibilities.
GN_Running_GetScheduleFingerprint()124 unsigned int GN_Running_GetScheduleFingerprint ()
125 {
126 unsigned short sum;
127 unsigned int i;
128 unsigned int j;
129
130 sum = (unsigned short) 0xffff & (unsigned long)
131 (BB_Loops * BB_VoiceCount * BB_TotalDuration);
132
133 for (i = 0; i < BB_VoiceCount; i++)
134 {
135 for (j = 0; j < BB_Voice[i].EntryCount; j++)
136 {
137 ++sum;
138 sum += (unsigned short) 0xffff & (unsigned long)
139 ((1 + BB_Voice[i].type) *
140 BB_Voice[i].Entry[j].duration *
141 BB_Voice[i].Entry[j].basefreq_start *
142 BB_Voice[i].Entry[j].beatfreq_start_HALF);
143 }
144 }
145
146 GN_ScheduleFingerprint = sum;
147 return GN_ScheduleFingerprint;
148 }
149
150 /*
151 //NOTE: THIS WAS NICE... except turns out that different endline
152 /chars, etc., made it not valid across platforms.
153 ////////////////////////////////////////////////////////////////
154 //Basically just a PRNG based on the Adler-32 algo: a given seed will
155 //always return the same arbitrary number for a given file.
156 //Seed can be any unsigned int range value, but 0 seems a weak
157 //choice (since fingerprint wouldn't really begin until a non-zero
158 //input occurred, slightly reducing possible outcomes related to filesize).
159 //This should be run ONLY when a new file is opened (not to, say, check a
160 //file). Also, only half of this number is sent over network (because
161 //I can't imagine distinguishing between more than a hundred files).
162 unsigned int GN_Running_GetScheduleFingerprint (char *filename, unsigned int seed)
163 {
164 const unsigned int BASE = 65521U; // largest prime smaller than 65536
165 unsigned int sum;
166 unsigned int file_len = 0;
167 FILE *stream;
168
169 if ((stream = fopen (filename, "rb")) == NULL)
170 {
171 printf ("Couldn't open requested file \"%s\"\n", filename);
172 return 0;
173 }
174
175 // split to make Adler32 component sums:
176 sum = (seed >> 16) & 0xffff;
177 seed &= 0xffff;
178
179 while (feof (stream) == 0)
180 {
181 seed += (unsigned char) fgetc (stream);
182 if (seed >= BASE)
183 seed -= BASE;
184 sum += seed;
185 if (sum >= BASE)
186 sum -= BASE;
187 ++file_len;
188 }
189
190 fclose (stream);
191 printf ("Measured size of file (bytes): %u\n", file_len);
192 GN_ScheduleFingerprint_FULL = seed | (sum << 16);
193 return GN_ScheduleFingerprint_FULL;
194 }
195 */
196