Changeset d604d68 in orbit
- Timestamp:
- 12/19/12 13:11:34 (9 years ago)
- Branches:
- master, RawEEG, Raw_EEG_Plot, Servo, Tab_Interface, pyramid
- Children:
- 948f49a, 66477ef
- Parents:
- 85e0208
- Location:
- android/src/info/puzzlebox/orbit
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
android/src/info/puzzlebox/orbit/MainActivity.java
r85e0208 rd604d68 972 972 manualControl(); 973 973 974 } // demoMode 975 976 977 public static final int samplePerSecond = 44100; 978 final double sampleTime = 1/(double)samplePerSecond; 979 980 final double longHIGH = 0.000875-sampleTime*2;//half period HIGH of code '1', in s 981 final double longLOW = 0.000729+sampleTime*3; 982 final double shortHIGH = 0.000458-sampleTime*2; 983 final double shortLOW = 0.000333+sampleTime*2; 984 985 final float[] waveLongHIGH=halfSineGen('u',longHIGH,samplePerSecond); 986 final float[] waveLongLOW=halfSineGen('d',longLOW,samplePerSecond); 987 final float[] waveShortHIGH=halfSineGen('u',shortHIGH,samplePerSecond); 988 final float[] waveShortLOW=halfSineGen('d',shortLOW,samplePerSecond); 989 final float[] waveBit[]= {concatFloat(waveShortHIGH,waveShortLOW),concatFloat(waveLongHIGH,waveLongLOW)}; 990 974 } // Manual Control Mode 991 975 992 976 public void manualControl() { … … 1007 991 } 1008 992 */ 1009 AndroidAudioDevice device = new AndroidAudioDevice();993 OrbitAudioCode orbit = new OrbitAudioCode(44100,false); 1010 994 1011 995 for (int j = 0; j<4; j++) 1012 device.writeSamples(code2wave(command2code(80,78,31,'A'),samplePerSecond,false));996 orbit.send(orbit.code2wave(orbit.command2code(80,78,31,'A'))); 1013 997 1014 device.writeSamples(initialWave(samplePerSecond,false));998 orbit.send(orbit.initialWave()); 1015 999 1016 1000 for (int j = 0; j<50; j++){ 1017 device.writeSamples(code2wave(command2code(80,78,31,'A'),samplePerSecond,false)); 1018 1019 /*try{ 1020 Thread.sleep(80); 1021 } catch (InterruptedException e){ 1022 e.printStackTrace(); 1023 }*/ 1024 } 1001 orbit.send(orbit.code2wave(orbit.command2code(80,78,31,'A'))); 1002 } 1003 orbit.releasetrack(); 1025 1004 } 1026 1027 /** 1028 * command2code, turn throttle, pitch and yaw to IR code (in sound data form). 1029 * @param throttle: 0~127, nothing will happen if this value is below 30. 1030 * @param yaw: 0~127, normally 78 will keep orbit from rotating. 1031 * @param pitch: 0~63, normally 31 will stop the top propeller. 1032 * @param channel: 'A' or 'B' or 'C', depend on which channel you want to pair to the orbit. You can fly at most 3 orbit in a same room. 1033 * @return 1034 */ 1035 1036 int command2code(int throttle, int yaw, int pitch, char channel){ 1037 int code = throttle << 21; 1038 code += 1 << 20 ; 1039 code += yaw << 12; 1040 code += pitch << 4 ; 1041 // weird, if use int code= throttle << 21 + 1<<20 + yaw <<12 +pitch<<4; it won't work. 1042 switch (channel){ 1043 case 'A': code += 1 << 11; 1044 break; 1045 // case 'B': break; 1046 case 'C': code += 1 << 19; 1047 break; 1048 default: break; 1049 } 1050 int checkSum=0; 1051 for (int i=0; i<7; i++) 1052 checkSum += (code >> 4*i) & 15; //15=0x0F=0b00001111 1053 checkSum = 16-(checkSum & 15); 1054 return code + checkSum; 1055 } 1056 1057 /** code2wave(,,) 1058 * generate 1 full fly command in wave form on the fly. 1059 * @param code: the control code array need to be turned into 1060 * @param sampleRate: sample rate supported on certain Android device, normally 44100, but on some device it is 48000. 1061 * @param flip: on certain Android device, the signal need to be flipped. true means flip, false means not. 1062 * @return fully assembled fly command in a float array, to be written in buffer and sent out. 1063 */ 1064 1065 float[] code2wave(int code, int sampleRate, boolean flip){ 1066 1067 //float[] wave = concatFloat(concatFloat(waveLongLOW,concatFloat(waveLongHIGH,waveShortLOW)),concatFloat(waveLongHIGH,waveShortLOW)); 1068 /* 1069 final double longHIGH = 0.000875-sampleTime*2;//half period HIGH of code '1', in s 1070 final double longLOW = 0.000729+sampleTime*5; 1071 final double shortHIGH = 0.000458-sampleTime*3; 1072 final double shortLOW = 0.000333+sampleTime*3; 1073 */ 1074 float[] wave = halfSineGen('d',longLOW,sampleRate); 1075 float[] tempWave = concatFloat(halfSineGen('u',longHIGH-sampleTime*2,sampleRate),halfSineGen('d',shortLOW+sampleTime*2,sampleRate)); 1076 wave = concatFloat(wave,tempWave); 1077 wave = concatFloat(wave,tempWave); 1078 /*int waveLength = waveLongLOW.length+(waveLongHIGH.length+waveShortLOW.length)*2; 1079 1080 byte sum=0; 1081 for (int i=0; i<28; i++){ 1082 sum += (code >>> i) & 1) 1083 } 1084 waveLength+=sum*(waveLongHIGH.length+waveLongLOW.length)+(28-sum)*(waveShortHIGH.length+waveShortLOW.length); 1085 waveLength+=waveLongHIGH.length; 1086 1087 float[] wave=new float[waveLength]; 1088 */ 1089 1090 for (int i=27; i>=0; i--) 1091 wave=concatFloat(wave,waveBit[((code >>> i) & 1)]); 1092 1093 wave=concatFloat(wave,waveLongHIGH); 1094 //float[] zeroArray= new float[1024]; 1095 1096 if (flip) 1097 for (int i=0; i<wave.length; i++) 1098 wave[i]=-wave[i]; 1099 1100 wave=concatFloat(wave,new float[4096]); 1101 1102 return wave; 1103 } 1104 1105 /* 1106 float[] zerosFloat(int num){ 1107 return new float[num]; 1108 } 1109 */ 1110 1111 /* 1112 float[] bitGen(short bit, int sampleRate){ 1113 1114 if (bit == 0) 1115 return concatFloat(waveShortHIGH,waveShortLOW); 1116 else 1117 return concatFloat(waveLongHIGH,waveLongLOW); 1118 } 1119 */ 1120 1121 float[] initialWave(int sampleRate, boolean flip){ 1122 final double initLongHIGH=0.001-sampleTime*1; //seconds 1123 final double initLongZERO=0.002+sampleTime*1; 1124 final double initMediumLOW=0.0005-sampleTime*1; 1125 final double initShortHIGH=0.0001+sampleTime*1; 1126 final double initShortLOW=0.00018; 1127 final double initPause=0.010; 1128 final double initSpace=0.084354; 1129 1130 final float[] waveInitLongHIGH=halfSineGen('u',initLongHIGH,sampleRate); 1131 final int waveInitLongZEROLength= (int)Math.floor(initLongZERO*sampleRate); 1132 final float[] waveInitMediumLOW=halfSineGen('d',initMediumLOW,sampleRate); 1133 final float[] waveInitShortHIGH=halfSineGen('u',initShortHIGH,sampleRate); 1134 final float[] waveInitShortLOW=halfSineGen('d',initShortLOW,sampleRate); 1135 1136 final float[] waveLongHLongZERO= concatFloat(waveInitLongHIGH,new float[waveInitLongZEROLength]); 1137 final float[] waveMediumLShortH = concatFloat(waveInitMediumLOW,waveInitShortHIGH); 1138 final float[] waveShortHShortL = concatFloat(waveInitShortHIGH, waveInitShortLOW); 1139 1140 float[] initWaveOriginal = concatFloat(waveLongHLongZERO,waveLongHLongZERO); 1141 initWaveOriginal = concatFloat(initWaveOriginal,waveInitLongHIGH); 1142 initWaveOriginal = concatFloat(initWaveOriginal, waveMediumLShortH); 1143 1144 float[] initWave123 = concatFloat(initWaveOriginal,waveInitMediumLOW); 1145 float[] initWave456 = concatFloat(initWaveOriginal,waveInitShortLOW); 1146 1147 for (int i=0; i<4; i++){ 1148 initWave123 = concatFloat(initWave123,waveShortHShortL); 1149 initWave456 = concatFloat(initWave456,waveShortHShortL); 1150 } 1151 1152 initWave123 = concatFloat(initWave123,waveInitShortHIGH); 1153 initWave123 = concatFloat(initWave123,waveMediumLShortH); 1154 1155 initWave456 = concatFloat(initWave456,waveInitShortHIGH); 1156 initWave456 = concatFloat(initWave456,waveMediumLShortH); 1157 1158 if (flip){ 1159 for (int i=0; i<initWave123.length; i++) 1160 initWave123[i]=-initWave123[i]; 1161 1162 for (int i=0; i<initWave456.length; i++) 1163 initWave456[i]=-initWave456[i]; 1164 } 1165 1166 1167 int initPauseInSamples=(int)Math.floor(initPause*sampleRate); 1168 initWave123 = concatFloat(initWave123,new float[initPauseInSamples]); 1169 initWave456 = concatFloat(initWave456,new float[initPauseInSamples]); 1170 1171 float[] initWave123Pattern=initWave123; 1172 float[] initWave456Pattern=initWave456; 1173 1174 1175 for (int i=0; i<2; i++){ 1176 initWave123 = concatFloat(initWave123, initWave123Pattern); 1177 initWave456 = concatFloat(initWave456, initWave456Pattern); 1178 } 1179 1180 return concatFloat(initWave123,initWave456); 1181 1182 } 1183 1184 /** concatFloatAll 1185 * since Arrays.copyOf is added in API level 9, 1186 * so this not compatible with API level < 9, or known as Android 2.3 * 1187 * @param arbitrary numbers of arrays that you want to connect together 1188 * @return one array that contains all the parameters in a single array. 1189 */ 1190 1191 /* 1192 public float[] concatFloatAll(float[] first, float[]... rest) { 1193 int totalLength = first.length; 1194 for (float[] array : rest) { 1195 totalLength += array.length; 1196 } 1197 float[] result= Arrays.copyOf(first, totalLength); 1198 int offset = first.length; 1199 for (float[] array : rest){ 1200 System.arraycopy(array, 0, result, offset, array.length); 1201 offset += array.length; 1202 } 1203 return result; 1204 } 1205 */ 1206 1207 public float[] concatFloat(float[] A, float[] B){ 1208 float[] C = new float[A.length+B.length]; 1209 System.arraycopy(A, 0, C, 0, A.length); 1210 System.arraycopy(B, 0, C, A.length, B.length); 1211 return C; 1212 } 1213 1214 float[] halfSineGen(char dir,double halfPeriod, int sampleRate) { 1215 int halfPeriodInSamples = (int)Math.floor(halfPeriod*sampleRate); 1216 float halfSine[] = new float[halfPeriodInSamples]; 1217 double increment = Math.PI/(halfPeriod*sampleRate); 1218 double angle = 0; 1219 1220 if (dir == 'u') 1221 for (int i =0; i<halfPeriodInSamples;i++) 1222 { 1223 halfSine[i]=(float)Math.sin(angle); 1224 angle += increment; 1225 } 1226 else if (dir == 'd'){ 1227 angle = Math.PI; 1228 for (int i =0; i<halfPeriodInSamples;i++) 1229 { 1230 halfSine[i]=(float)Math.sin(angle); 1231 angle += increment; 1232 } 1233 } 1234 1235 return halfSine; 1236 } 1005 1237 1006 1238 1007 } // MainActivity 1239 1008 1240 1241 class AndroidAudioDevice {1242 AudioTrack track;1243 short[] buffer = new short[6144];1244 1245 public AndroidAudioDevice()1246 {1247 int minSize = AudioTrack.getMinBufferSize( 44100, AudioFormat.CHANNEL_OUT_STEREO,AudioFormat.ENCODING_PCM_16BIT);1248 track = new AudioTrack(AudioManager.STREAM_MUSIC,44100,AudioFormat.CHANNEL_OUT_STEREO,AudioFormat.ENCODING_PCM_16BIT,minSize, AudioTrack.MODE_STREAM);1249 track.play();1250 }1251 1252 public void writeSamples(float[] samples)1253 {1254 fillBuffer(samples);1255 track.write(buffer,0,2*samples.length);1256 }1257 1258 private void fillBuffer(float[] samples)1259 {1260 if(buffer.length < 2*samples.length)1261 buffer=new short[2*samples.length];1262 1263 float increment = (float)((2*Math.PI)*500/MainActivity.samplePerSecond);1264 float angle = 0;1265 1266 for (int i=0; i< samples.length; i++){1267 buffer[2*i+1]=(short)(Math.sin(angle)*Short.MAX_VALUE);1268 buffer[2*i]=(short)(samples[i]*Short.MAX_VALUE);1269 angle += increment;1270 }1271 }1272 public void releasetrack(){1273 track.release();1274 }1275 }
Note: See TracChangeset
for help on using the changeset viewer.