sound.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /*
  2. Copyright (C) 2004-2005 Michael Liebscher
  3. Copyright (C) 1997-2001 Id Software, Inc.
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. /*
  17. * sound.c:
  18. *
  19. * Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
  20. * Date: 2004
  21. *
  22. * Acknowledgement:
  23. * This code was derived from Quake II, and was originally
  24. * written by Id Software, Inc.
  25. *
  26. * Acknowledgement:
  27. * Portion of this code was derived from Quake II Evolved.
  28. *
  29. */
  30. #include "../wolfiphone.h"
  31. #define MAX_PLAYSOUNDS 128
  32. #define MAX_CHANNELS 64
  33. PRIVATE playSound_t s_playSounds[ MAX_PLAYSOUNDS ];
  34. PRIVATE playSound_t s_freePlaySounds;
  35. PRIVATE playSound_t s_pendingPlaySounds;
  36. PRIVATE channel_t s_channels[ MAX_CHANNELS ];
  37. PRIVATE int s_numChannels;
  38. PRIVATE listener_t s_listener;
  39. PRIVATE int s_frameCount;
  40. PRIVATE _boolean s_activeApp;
  41. _boolean sound_initialized = false;
  42. cvar_t *s_initSound;
  43. cvar_t *s_masterVolume;
  44. cvar_t *s_sfxVolume;
  45. cvar_t *s_musicVolume;
  46. cvar_t *s_minDistance;
  47. cvar_t *s_maxDistance;
  48. cvar_t *s_rolloffFactor;
  49. cvar_t *s_dopplerFactor;
  50. cvar_t *s_dopplerVelocity;
  51. /////////////////////////////////////////////////////////////////////
  52. //
  53. // Sound Channels
  54. //
  55. /////////////////////////////////////////////////////////////////////
  56. /*
  57. -----------------------------------------------------------------------------
  58. Function: Sound_AllocChannels -Allocate sound channels.
  59. Parameters: Nothing.
  60. Returns: Nothing.
  61. Notes:
  62. -----------------------------------------------------------------------------
  63. */
  64. PRIVATE void Sound_AllocChannels( void )
  65. {
  66. channel_t *ch;
  67. int i;
  68. for( i = 0, ch = s_channels ; i < MAX_CHANNELS ; ++i, ++ch )
  69. {
  70. pfalGenSources( 1, &ch->sourceName );
  71. if( pfalGetError() != AL_NO_ERROR )
  72. {
  73. break;
  74. }
  75. s_numChannels++;
  76. }
  77. }
  78. /*
  79. -----------------------------------------------------------------------------
  80. Function: Sound_FreeChannels -Free sound channels.
  81. Parameters: Nothing.
  82. Returns: Nothing.
  83. Notes:
  84. -----------------------------------------------------------------------------
  85. */
  86. PRIVATE void Sound_FreeChannels( void )
  87. {
  88. channel_t *ch;
  89. int i;
  90. for( i = 0, ch = s_channels; i < s_numChannels; i++, ch++)
  91. {
  92. pfalDeleteSources( 1, &ch->sourceName );
  93. memset( ch, 0, sizeof( *ch ) );
  94. }
  95. s_numChannels = 0;
  96. }
  97. /*
  98. -----------------------------------------------------------------------------
  99. Function: Sound_FreeChannels -Free sound channels.
  100. Parameters: Nothing.
  101. Returns: Nothing.
  102. Notes:
  103. -----------------------------------------------------------------------------
  104. */
  105. PRIVATE int Sound_ChannelState( channel_t *ch )
  106. {
  107. int state;
  108. pfalGetSourcei( ch->sourceName, AL_SOURCE_STATE, &state );
  109. return state;
  110. }
  111. PRIVATE void Sound_PlayChannel( channel_t *ch, sfx_t *sfx )
  112. {
  113. ch->sfx = sfx;
  114. pfalSourcei( ch->sourceName, AL_BUFFER, sfx->bufferNum );
  115. pfalSourcei( ch->sourceName, AL_LOOPING, ch->loopSound );
  116. pfalSourcei( ch->sourceName, AL_SOURCE_RELATIVE, AL_FALSE );
  117. pfalSourcePlay( ch->sourceName );
  118. }
  119. PRIVATE void Sound_StopChannel( channel_t *ch )
  120. {
  121. ch->sfx = NULL;
  122. pfalSourceStop( ch->sourceName );
  123. pfalSourcei( ch->sourceName, AL_BUFFER, 0 );
  124. #ifdef IPHONE
  125. // OpenAL on the iphone doesn't seem to stop sounds properly.
  126. // Maybe regenning the source will work...
  127. pfalDeleteSources( 1, &ch->sourceName );
  128. pfalGenSources( 1, &ch->sourceName );
  129. #endif
  130. }
  131. PRIVATE void Sound_SpatializeChannel( channel_t *ch )
  132. {
  133. // vec3_t position, velocity;
  134. // Update position and velocity
  135. if( ch->entNum == 0 || ! ch->distanceMult )
  136. {
  137. pfalSourcefv( ch->sourceName, AL_POSITION, s_listener.position );
  138. pfalSourcefv( ch->sourceName, AL_VELOCITY, s_listener.velocity );
  139. }
  140. else
  141. {
  142. if( ch->fixedPosition )
  143. {
  144. pfalSource3f( ch->sourceName, AL_POSITION, ch->position[1], ch->position[2], -ch->position[0] );
  145. pfalSource3f( ch->sourceName, AL_VELOCITY, 0, 0, 0 );
  146. }
  147. /* else
  148. {
  149. if( ch->loopSound )
  150. {
  151. Client_GetEntitySoundSpatialization( ch->loopNum, position, velocity );
  152. }
  153. else
  154. {
  155. Client_GetEntitySoundSpatialization( ch->entNum, position, velocity );
  156. }
  157. pfalSource3f( ch->sourceName, AL_POSITION, position[1], position[2], -position[0] );
  158. pfalSource3f( ch->sourceName, AL_VELOCITY, velocity[1], velocity[2], -velocity[0] );
  159. }
  160. */
  161. }
  162. // Update min/max distance
  163. if( ch->distanceMult )
  164. {
  165. pfalSourcef( ch->sourceName, AL_REFERENCE_DISTANCE, s_minDistance->value * ch->distanceMult );
  166. }
  167. else
  168. {
  169. pfalSourcef( ch->sourceName, AL_REFERENCE_DISTANCE, s_maxDistance->value );
  170. }
  171. pfalSourcef( ch->sourceName, AL_MAX_DISTANCE, s_maxDistance->value );
  172. // Update volume and rolloff factor
  173. pfalSourcef( ch->sourceName, AL_GAIN, s_sfxVolume->value * ch->volume );
  174. pfalSourcef( ch->sourceName, AL_ROLLOFF_FACTOR, s_rolloffFactor->value );
  175. }
  176. /*
  177. -----------------------------------------------------------------------------
  178. Function: Sound_PickChannel -
  179. Parameters:
  180. Returns:
  181. Notes:
  182. Tries to find a free channel, or tries to replace an active channel.
  183. -----------------------------------------------------------------------------
  184. */
  185. PUBLIC channel_t *Sound_PickChannel( W32 entNum, W32 entChannel )
  186. {
  187. channel_t *ch;
  188. int i;
  189. int firstToDie = -1;
  190. int oldestTime = iphoneFrameNum;
  191. for( i = 0, ch = s_channels ; i < s_numChannels ; ++i, ++ch )
  192. {
  193. // Don't let game sounds override streaming sounds
  194. if( ch->streaming )
  195. {
  196. continue;
  197. }
  198. // Check if this channel is active
  199. if( ! ch->sfx )
  200. {
  201. // Free channel
  202. firstToDie = i;
  203. break;
  204. }
  205. // Channel 0 never overrides
  206. if( entChannel != 0 && (ch->entNum == entNum && ch->entChannel == entChannel ) )
  207. {
  208. // Always override sound from same entity
  209. firstToDie = i;
  210. break;
  211. }
  212. // Replace the oldest sound
  213. if( ch->startTime < oldestTime )
  214. {
  215. oldestTime = ch->startTime;
  216. firstToDie = i;
  217. }
  218. }
  219. if( firstToDie == -1 )
  220. {
  221. return NULL;
  222. }
  223. ch = &s_channels[ firstToDie ];
  224. ch->entNum = entNum;
  225. ch->entChannel = entChannel;
  226. ch->startTime = iphoneFrameNum;
  227. // Make sure this channel is stopped
  228. Sound_StopChannel( ch );
  229. return ch;
  230. }
  231. /////////////////////////////////////////////////////////////////////
  232. // End of Sound Channels
  233. /////////////////////////////////////////////////////////////////////
  234. /*
  235. -----------------------------------------------------------------------------
  236. Function: Sound_AddLoopingSounds -
  237. Parameters: Nothing.
  238. Returns: Nothing.
  239. Notes:
  240. Entities with a a->sound field will generate looping sounds that are
  241. automatically started and stopped as the entities are sent to the
  242. client.
  243. -----------------------------------------------------------------------------
  244. */
  245. PRIVATE void Sound_AddLoopingSounds( void )
  246. {
  247. }
  248. PRIVATE playSound_t *Sound_AllocPlaySound( void )
  249. {
  250. playSound_t *ps;
  251. ps = s_freePlaySounds.next;
  252. if( ps == &s_freePlaySounds )
  253. {
  254. return NULL; // No free playSounds
  255. }
  256. ps->prev->next = ps->next;
  257. ps->next->prev = ps->prev;
  258. return ps;
  259. }
  260. PRIVATE void Sound_FreePlaySound( playSound_t *ps )
  261. {
  262. ps->prev->next = ps->next;
  263. ps->next->prev = ps->prev;
  264. // Add to free list
  265. ps->next = s_freePlaySounds.next;
  266. s_freePlaySounds.next->prev = ps;
  267. ps->prev = &s_freePlaySounds;
  268. s_freePlaySounds.next = ps;
  269. }
  270. /*
  271. -----------------------------------------------------------------------------
  272. Function: Sound_IssuePlaySounds -
  273. Parameters:
  274. Returns: Nothing.
  275. Notes:
  276. Take the next playsound and begin it on the channel.
  277. This is never called directly by Sound_StartSound*, but only by the update loop.
  278. -----------------------------------------------------------------------------
  279. */
  280. PRIVATE void Sound_IssuePlaySounds( void )
  281. {
  282. playSound_t *ps;
  283. channel_t *ch;
  284. while( 1 )
  285. {
  286. ps = s_pendingPlaySounds.next;
  287. if( ps == &s_pendingPlaySounds )
  288. {
  289. break; // No more pending playSounds
  290. }
  291. if( ps->beginTime > iphoneFrameNum )
  292. {
  293. break; // No more pending playSounds this frame
  294. }
  295. // Pick a channel and start the sound effect
  296. ch = Sound_PickChannel( ps->entNum, ps->entChannel );
  297. if( ! ch )
  298. {
  299. if( ps->sfx->name[ 0 ] == '#' )
  300. Com_DPrintf( "Dropped sound %s\n", &ps->sfx->name[1]);
  301. else
  302. Com_DPrintf( "Dropped sound sound/%s\n", ps->sfx->name);
  303. Sound_FreePlaySound( ps );
  304. continue;
  305. }
  306. ch->loopSound = false;
  307. ch->fixedPosition = ps->fixedPosition;
  308. vectorCopy( ps->position, ch->position );
  309. ch->volume = ps->volume;
  310. if( ps->attenuation != ATTN_NONE )
  311. {
  312. ch->distanceMult = 1.0f / ps->attenuation;
  313. }
  314. else
  315. {
  316. ch->distanceMult = 0.0;
  317. }
  318. Sound_SpatializeChannel( ch );
  319. Sound_PlayChannel( ch, ps->sfx );
  320. // Free the playSound
  321. Sound_FreePlaySound( ps );
  322. }
  323. }
  324. /*
  325. -----------------------------------------------------------------------------
  326. Function: Sound_StartSound -
  327. Parameters:
  328. Returns: Nothing.
  329. Notes:
  330. Validates the parms and queues the sound up.
  331. If origin is NULL, the sound will be dynamically sourced from the
  332. entity.
  333. entChannel 0 will never override a playing sound.
  334. -----------------------------------------------------------------------------
  335. */
  336. PUBLIC void Sound_StartSound( const vec3_t position, int entNum, int entChannel, sfx_t *sfx, float volume, float attenuation, int timeOfs )
  337. {
  338. playSound_t *ps, *sort;
  339. if( ! sound_initialized )
  340. {
  341. return;
  342. }
  343. if( ! sfx )
  344. {
  345. return;
  346. }
  347. // Make sure the sound is loaded
  348. if( ! Sound_LoadSound( sfx ) )
  349. {
  350. return;
  351. }
  352. // Allocate a playSound
  353. ps = Sound_AllocPlaySound();
  354. if( ! ps )
  355. {
  356. if( sfx->name[0] == '#' )
  357. Com_DPrintf( "Dropped sound %s\n", &sfx->name[1] );
  358. else
  359. Com_DPrintf( "Dropped sound sound/%s\n", sfx->name);
  360. return;
  361. }
  362. ps->sfx = sfx;
  363. ps->entNum = entNum;
  364. ps->entChannel = entChannel;
  365. if( position )
  366. {
  367. ps->fixedPosition = true;
  368. vectorCopy( position, ps->position );
  369. }
  370. else
  371. {
  372. ps->fixedPosition = false;
  373. }
  374. ps->volume = volume;
  375. ps->attenuation = attenuation;
  376. ps->beginTime = iphoneFrameNum;
  377. // Sort into the pending playSounds list
  378. for( sort = s_pendingPlaySounds.next ; sort != &s_pendingPlaySounds && sort->beginTime < ps->beginTime ; sort = sort->next )
  379. {
  380. ;
  381. }
  382. ps->next = sort;
  383. ps->prev = sort->prev;
  384. ps->next->prev = ps;
  385. ps->prev->next = ps;
  386. }
  387. PUBLIC void Sound_StartLocalSound( const char *filename )
  388. {
  389. sfx_t *sfx;
  390. if( ! sound_initialized )
  391. {
  392. return;
  393. }
  394. sfx = Sound_RegisterSound( filename );
  395. if( ! sfx )
  396. {
  397. Com_Printf( "Sound_StartLocalSound: could not cache (%s)\n", filename );
  398. return;
  399. }
  400. Sound_StartSound( NULL, 0, 0, sfx, 1, ATTN_NONE, 0 );
  401. }
  402. PUBLIC void Sound_StopAllSounds( void )
  403. {
  404. channel_t *ch;
  405. int i;
  406. if( ! sound_initialized )
  407. {
  408. return;
  409. }
  410. // Clear all the playSounds
  411. memset( s_playSounds, 0, sizeof( s_playSounds ) );
  412. s_freePlaySounds.next = s_freePlaySounds.prev = &s_freePlaySounds;
  413. s_pendingPlaySounds.next = s_pendingPlaySounds.prev = &s_pendingPlaySounds;
  414. for( i = 0 ; i < MAX_PLAYSOUNDS ; ++i )
  415. {
  416. s_playSounds[ i ].prev = &s_freePlaySounds;
  417. s_playSounds[ i ].next = s_freePlaySounds.next;
  418. s_playSounds[ i ].prev->next = &s_playSounds[ i ];
  419. s_playSounds[ i ].next->prev = &s_playSounds[ i ];
  420. }
  421. // Stop all the channels
  422. for( i = 0, ch = s_channels ; i < s_numChannels ; ++i, ++ch )
  423. {
  424. if( ! ch->sfx )
  425. {
  426. continue;
  427. }
  428. Sound_StopChannel( ch );
  429. }
  430. // Reset frame count
  431. s_frameCount = 0;
  432. }
  433. /*
  434. -----------------------------------------------------------------------------
  435. Function: Sound_Update -
  436. Parameters: Nothing.
  437. Returns: Nothing.
  438. Notes:
  439. Called once each time through the main loop.
  440. -----------------------------------------------------------------------------
  441. */
  442. PUBLIC void Sound_Update( const vec3_t position, const vec3_t velocity, const vec3_t at, const vec3_t up)
  443. {
  444. channel_t *ch;
  445. int i, total = 0;
  446. if( ! sound_initialized )
  447. {
  448. return;
  449. }
  450. // Bump frame count
  451. s_frameCount++;
  452. // Set up listener
  453. vectorSet( s_listener.position, position[1], position[2], -position[0] );
  454. vectorSet( s_listener.velocity, velocity[1], velocity[2], -velocity[0] );
  455. vectorSet( &s_listener.orientation[0], at[1], -at[2], -at[0] );
  456. vectorSet( &s_listener.orientation[3], up[1], -up[2], -up[0] );
  457. pfalListenerfv( AL_POSITION, s_listener.position );
  458. pfalListenerfv( AL_VELOCITY, s_listener.velocity );
  459. pfalListenerfv( AL_ORIENTATION, s_listener.orientation );
  460. pfalListenerf( AL_GAIN, (s_activeApp) ? s_masterVolume->value : 0.0);
  461. // Set state
  462. pfalDistanceModel( AL_INVERSE_DISTANCE_CLAMPED );
  463. pfalDopplerFactor( s_dopplerFactor->value );
  464. pfalDopplerVelocity( s_dopplerVelocity->value );
  465. // Stream background track
  466. Sound_StreamBGTrack();
  467. // Add looping sounds
  468. Sound_AddLoopingSounds();
  469. // Issue playSounds
  470. Sound_IssuePlaySounds();
  471. // Update spatialization for all sounds
  472. for( i = 0, ch = s_channels ; i < s_numChannels ; ++i, ++ch )
  473. {
  474. if( ! ch->sfx )
  475. {
  476. continue; // Not active
  477. }
  478. // Check for stop
  479. if( ch->loopSound )
  480. {
  481. if( ch->loopFrame != s_frameCount )
  482. {
  483. Sound_StopChannel( ch );
  484. continue;
  485. }
  486. }
  487. else
  488. {
  489. if( Sound_ChannelState(ch) == AL_STOPPED )
  490. {
  491. Sound_StopChannel( ch );
  492. continue;
  493. }
  494. }
  495. // Respatialize channel
  496. Sound_SpatializeChannel( ch );
  497. total++;
  498. }
  499. }
  500. PUBLIC void Sound_Activate( _boolean active )
  501. {
  502. s_activeApp = active;
  503. if( ! sound_initialized )
  504. {
  505. return;
  506. }
  507. pfalListenerf( AL_GAIN, ( active ) ? s_masterVolume->value : 0.0 );
  508. }
  509. /////////////////////////////////////////////////////////////////////
  510. //
  511. // Console Commands
  512. //
  513. /////////////////////////////////////////////////////////////////////
  514. PRIVATE void Sound_Play_f( void )
  515. {
  516. int i = 1;
  517. char name[ MAX_GAMEPATH ];
  518. if( Cmd_Argc() == 1 )
  519. {
  520. Com_Printf( "Usage: play <soundfile>\n" );
  521. return;
  522. }
  523. while( i < Cmd_Argc() )
  524. {
  525. my_strlcpy( name, Cmd_Argv( i ), sizeof( name ) );
  526. Sound_StartLocalSound( name );
  527. i++;
  528. }
  529. }
  530. PRIVATE void Sound_StopSound_f( void )
  531. {
  532. Sound_StopAllSounds();
  533. }
  534. /*
  535. -----------------------------------------------------------------------------
  536. Function: Sound_Restart_f -Console function to restart the sound module.
  537. Parameters: Nothing.
  538. Returns: Nothing.
  539. Notes:
  540. Restart the sound subsystem so it can pick up new parameters and flush
  541. all sounds.
  542. -----------------------------------------------------------------------------
  543. */
  544. PRIVATE void Sound_Restart_f( void )
  545. {
  546. Sound_Shutdown();
  547. Sound_Init();
  548. }
  549. /////////////////////////////////////////////////////////////////////
  550. // End of Console Commands
  551. /////////////////////////////////////////////////////////////////////
  552. extern void Sound_SoundList_f( void );
  553. PRIVATE void Sound_Register( void )
  554. {
  555. s_initSound = Cvar_Get( "s_initSound", "1", CVAR_INIT );
  556. s_masterVolume = Cvar_Get( "s_masterVolume", "1.0", CVAR_ARCHIVE );
  557. s_sfxVolume = Cvar_Get( "s_sfxVolume", "1.0", CVAR_ARCHIVE );
  558. s_musicVolume = Cvar_Get( "s_musicVolume", "1.0", CVAR_ARCHIVE );
  559. s_minDistance = Cvar_Get( "s_minDistance", "0.0", CVAR_ARCHIVE );
  560. s_maxDistance = Cvar_Get( "s_maxDistance", "1.0", CVAR_ARCHIVE );
  561. s_rolloffFactor = Cvar_Get( "s_rolloffFactor", "1.0", CVAR_ARCHIVE );
  562. s_dopplerFactor = Cvar_Get( "s_dopplerFactor", "1.0", CVAR_ARCHIVE );
  563. s_dopplerVelocity = Cvar_Get( "s_dopplerVelocity", "0.0", CVAR_ARCHIVE );
  564. Cmd_AddCommand( "play", Sound_Play_f );
  565. Cmd_AddCommand( "stopsound", Sound_StopSound_f );
  566. Cmd_AddCommand( "listSounds", Sound_SoundList_f );
  567. Cmd_AddCommand( "snd_restart", Sound_Restart_f );
  568. }
  569. PUBLIC void Sound_Init( void )
  570. {
  571. Com_Printf( "\n------- Sound Initialization -------\n" );
  572. Sound_Register();
  573. if( ! Sound_Device_Setup() )
  574. {
  575. Com_Printf( "------------------------------------\n" );
  576. return;
  577. }
  578. sound_initialized = true;
  579. Sound_AllocChannels();
  580. Sound_StopAllSounds();
  581. Com_Printf( "------------------------------------\n" );
  582. }
  583. PUBLIC void Sound_Shutdown( void )
  584. {
  585. Cmd_RemoveCommand( "play" );
  586. Cmd_RemoveCommand( "stopsound" );
  587. Cmd_RemoveCommand( "listSounds" );
  588. Cmd_RemoveCommand( "snd_restart" );
  589. if( ! sound_initialized )
  590. {
  591. return;
  592. }
  593. Sound_FreeSounds();
  594. Sound_FreeChannels();
  595. Sound_Device_Shutdown();
  596. sound_initialized = false;
  597. }